text:
package conf // import "bosun.org/cmd/bosun/conf"

import (
	"encoding/json"
	"fmt"
	htemplate "html/template"
	"io/ioutil"
	"net"
	"net/http"
	"net/mail"
	"net/url"
	"os"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	ttemplate "text/template"
	"time"

	"bosun.org/cmd/bosun/conf/parse"
	"bosun.org/cmd/bosun/expr"
	eparse "bosun.org/cmd/bosun/expr/parse"
	"bosun.org/graphite"
	"bosun.org/models"
	"bosun.org/opentsdb"
	"bosun.org/slog"
	"github.com/MiniProfiler/go/miniprofiler"
	"github.com/influxdata/influxdb/client"
)

type Conf struct {
	Vars
	Name            string        // Config file name
	CheckFrequency  time.Duration // Time between alert checks: 5m
	DefaultRunEvery int           // Default number of check intervals to run each alert: 1
	HTTPListen      string        // Web server listen address: :80
	Hostname        string
	RelayListen     string // OpenTSDB relay listen address: :4242
	SMTPHost        string // SMTP address: ny-mail:25
	SMTPUsername    string // SMTP username
	SMTPPassword    string // SMTP password
	Ping            bool
	PingDuration    time.Duration // Duration from now to stop pinging hosts based on time since the host tag was touched
	EmailFrom       string
	StateFile       string
	LedisDir        string
	LedisBindAddr   string

	RedisHost     string
	RedisDb       int
	RedisPassword string

	TimeAndDate      []int // timeanddate.com cities list
	ResponseLimit    int64
	SearchSince      opentsdb.Duration
	UnknownTemplate  *Template
	UnknownThreshold int
	Templates        map[string]*Template
	Alerts           map[string]*Alert
	Notifications    map[string]*Notification `json:"-"`
	RawText          string
	Macros           map[string]*Macro
	Lookups          map[string]*Lookup
	Squelch          Squelches `json:"-"`
	Quiet            bool
	NoSleep          bool
	ShortURLKey      string
	InternetProxy    string
	MinGroupSize     int

	TSDBHost             string                    // OpenTSDB relay and query destination: ny-devtsdb04:4242
	TSDBVersion          *opentsdb.Version         // If set to 2.2 , enable passthrough of wildcards and filters, and add support for groupby
	GraphiteHost         string                    // Graphite query host: foo.bar.baz
	GraphiteHeaders      []string                  // extra http headers when querying graphite.
	LogstashElasticHosts expr.LogstashElasticHosts // CSV Elastic Hosts (All part of the same cluster) that stores logstash documents, i.e http://ny-elastic01:9200. Only works with elastc pre-v2, and expects the schema to be logstash's default.
	ElasticHosts         expr.ElasticHosts         // CSV Elastic Hosts (All part of the same cluster), i.e http://ny-elastic01:9200. Only works with elastic v2+, and unlike logstash it is designed to be able to use various elastic schemas.
	InfluxConfig         client.Config

	AnnotateElasticHosts []string // CSV of Elastic Hosts, currently the only backend in annotate
	AnnotateIndex        string   // name of index / table

	tree            *parse.Tree
	node            parse.Node
	unknownTemplate string
	bodies          *htemplate.Template
	subjects        *ttemplate.Template
	squelch         []string
}

// TSDBContext returns an OpenTSDB context limited to
// c.ResponseLimit. A nil context is returned if TSDBHost is not set.
func (c *Conf) TSDBContext() opentsdb.Context {
	if c.TSDBHost == "" {
		return nil
	}
	return opentsdb.NewLimitContext(c.TSDBHost, c.ResponseLimit, *c.TSDBVersion)
}

// GraphiteContext returns a Graphite context. A nil context is returned if
// GraphiteHost is not set.
func (c *Conf) GraphiteContext() graphite.Context {
	if c.GraphiteHost == "" {
		return nil
	}
	if len(c.GraphiteHeaders) > 0 {
		headers := http.Header(make(map[string][]string))
		for _, s := range c.GraphiteHeaders {
			kv := strings.Split(s, ":")
			headers.Add(kv[0], kv[1])
		}
		return graphite.HostHeader{
			Host:   c.GraphiteHost,
			Header: headers,
		}
	}
	return graphite.Host(c.GraphiteHost)
}

type Squelch map[string]*regexp.Regexp

type Squelches struct {
	s []Squelch
}

func (s *Squelches) Add(v string) error {
	tags, err := opentsdb.ParseTags(v)
	if tags == nil && err != nil {
		return err
	}
	sq := make(Squelch)
	for k, v := range tags {
		re, err := regexp.Compile(v)
		if err != nil {
			return err
		}
		sq[k] = re
	}
	s.s = append(s.s, sq)
	return nil
}

func (s *Squelches) Squelched(tags opentsdb.TagSet) bool {
	for _, q := range s.s {
		if q.Squelched(tags) {
			return true
		}
	}
	return false
}

func (s Squelch) Squelched(tags opentsdb.TagSet) bool {
	if len(s) == 0 {
		return false
	}
	for k, v := range s {
		tagv, ok := tags[k]
		if !ok || !v.MatchString(tagv) {
			return false
		}
	}
	return true
}

func (c *Conf) AlertSquelched(a *Alert) func(opentsdb.TagSet) bool {
	return func(tags opentsdb.TagSet) bool {
		return c.Squelched(a, tags)
	}
}

func (c *Conf) Squelched(a *Alert, tags opentsdb.TagSet) bool {
	return c.Squelch.Squelched(tags) || a.Squelch.Squelched(tags)
}

// at marks the state to be on node n, for error reporting.
func (c *Conf) at(node parse.Node) {
	c.node = node
}

func (c *Conf) error(err error) {
	c.errorf(err.Error())
}

func (c *Conf) AnnotateEnabled() bool {
	return len(c.AnnotateElasticHosts) != 0
}

// errorf formats the error and terminates processing.
func (c *Conf) errorf(format string, args ...interface{}) {
	if c.node == nil {
		format = fmt.Sprintf("conf: %s: %s", c.Name, format)
	} else {
		location, context := c.tree.ErrorContext(c.node)
		format = fmt.Sprintf("conf: %s: at <%s>: %s", location, context, format)
	}
	panic(fmt.Errorf(format, args...))
}

// errRecover is the handler that turns panics into returns from the top
// level of Parse.
func errRecover(errp *error) {
	e := recover()
	if e != nil {
		switch err := e.(type) {
		case runtime.Error:
			panic(e)
		case error:
			*errp = err
		default:
			panic(e)
		}
	}
}

type Lookup struct {
	Text    string
	Name    string
	Tags    []string
	Entries []*Entry
}

func (lookup *Lookup) ToExpr() *ExprLookup {
	l := ExprLookup{
		Tags: lookup.Tags,
	}
	for _, entry := range lookup.Entries {
		l.Entries = append(l.Entries, entry.ExprEntry)
	}
	return &l
}

type Entry struct {
	*ExprEntry
	Def  string
	Name string
}

type Macro struct {
	Text  string
	Pairs []nodePair
	Name  string
}

type Alert struct {
	Text string
	Vars
	*Template        `json:"-"`
	Name             string
	Crit             *expr.Expr `json:",omitempty"`
	Warn             *expr.Expr `json:",omitempty"`
	Depends          *expr.Expr `json:",omitempty"`
	Squelch          Squelches  `json:"-"`
	CritNotification *Notifications
	WarnNotification *Notifications
	Unknown          time.Duration
	MaxLogFrequency  time.Duration
	IgnoreUnknown    bool
	UnknownsNormal   bool
	UnjoinedOK       bool `json:",omitempty"`
	Log              bool
	RunEvery         int
	returnType       models.FuncType

	template string
	squelch  []string
}

type Notifications struct {
	Notifications map[string]*Notification `json:"-"`
	// Table key -> table
	Lookups map[string]*Lookup
}

// Get returns the set of notifications based on given tags.
func (ns *Notifications) Get(c *Conf, tags opentsdb.TagSet) map[string]*Notification {
	nots := make(map[string]*Notification)
	for name, n := range ns.Notifications {
		nots[name] = n
	}
	for key, lookup := range ns.Lookups {
		l := lookup.ToExpr()
		val, ok := l.Get(key, tags)
		if !ok {
			continue
		}
		ns, err := c.parseNotifications(val)
		if err != nil {
			// Should already be checked by conf parser.
			panic(err)
		}
		for name, n := range ns {
			nots[name] = n
		}
	}
	return nots
}

// parseNotifications parses the comma-separated string v for notifications and
// returns them.
func (c *Conf) parseNotifications(v string) (map[string]*Notification, error) {
	ns := make(map[string]*Notification)
	for _, s := range strings.Split(v, ",") {
		s = strings.TrimSpace(s)
		n := c.Notifications[s]
		if n == nil {
			return nil, fmt.Errorf("unknown notification %s", s)
		}
		ns[s] = n
	}
	return ns, nil
}

type Template struct {
	Text string
	Vars
	Name    string
	Body    *htemplate.Template `json:"-"`
	Subject *ttemplate.Template `json:"-"`

	body, subject string
}

type Notification struct {
	Text string
	Vars
	Name         string
	Email        []*mail.Address
	Post, Get    *url.URL
	Body         *ttemplate.Template
	Print        bool
	Next         *Notification
	Timeout      time.Duration
	ContentType  string
	RunOnActions bool
	UseBody      bool

	next      string
	email     string
	post, get string
	body      string
}

func (n *Notification) MarshalJSON() ([]byte, error) {
	return nil, fmt.Errorf("conf: cannot json marshal notifications")
}

type Vars map[string]string

func ParseFile(fname string) (*Conf, error) {
	f, err := ioutil.ReadFile(fname)
	if err != nil {
		return nil, err
	}
	return New(fname, string(f))
}

func New(name, text string) (c *Conf, err error) {
	defer errRecover(&err)
	c = &Conf{
		Name:             name,
		CheckFrequency:   time.Minute * 5,
		DefaultRunEvery:  1,
		HTTPListen:       ":8070",
		StateFile:        "bosun.state",
		LedisDir:         "ledis_data",
		LedisBindAddr:    "127.0.0.1:9565",
		MinGroupSize:     5,
		PingDuration:     time.Hour * 24,
		ResponseLimit:    1 << 20, // 1MB
		SearchSince:      opentsdb.Day * 3,
		TSDBVersion:      &opentsdb.Version2_1,
		UnknownThreshold: 5,
		Vars:             make(map[string]string),
		Templates:        make(map[string]*Template),
		Alerts:           make(map[string]*Alert),
		Notifications:    make(map[string]*Notification),
		RawText:          text,
		bodies:           htemplate.New(name).Funcs(htemplate.FuncMap(defaultFuncs)),
		subjects:         ttemplate.New(name).Funcs(defaultFuncs),
		Lookups:          make(map[string]*Lookup),
		Macros:           make(map[string]*Macro),
	}
	c.tree, err = parse.Parse(name, text)
	if err != nil {
		c.error(err)
	}
	saw := make(map[string]bool)
	for _, n := range c.tree.Root.Nodes {
		c.at(n)
		switch n := n.(type) {
		case *parse.PairNode:
			c.seen(n.Key.Text, saw)
			c.loadGlobal(n)
		case *parse.SectionNode:
			c.loadSection(n)
		default:
			c.errorf("unexpected parse node %s", n)
		}
	}
	if c.Hostname == "" {
		c.Hostname = c.HTTPListen
		if strings.HasPrefix(c.Hostname, ":") {
			h, err := os.Hostname()
			if err != nil {
				c.at(nil)
				c.error(err)
			}
			c.Hostname = h + c.Hostname
		}
	}
	return
}

func (c *Conf) loadGlobal(p *parse.PairNode) {
	v := c.Expand(p.Val.Text, nil, false)
	switch k := p.Key.Text; k {
	case "checkFrequency":
		od, err := opentsdb.ParseDuration(v)
		if err != nil {
			c.error(err)
		}
		d := time.Duration(od)
		if d < time.Second {
			c.errorf("checkFrequency duration must be at least 1s")
		}
		c.CheckFrequency = d
	case "tsdbHost":
		if !strings.Contains(v, ":") && v != "" {
			v += ":4242"
		}
		c.TSDBHost = v
	case "tsdbVersion":
		sp := strings.Split(v, ".")
		if len(sp) != 2 {
			c.errorf("tsdbVersion must be in number.number form")
		}
		major, err := strconv.ParseInt(sp[0], 10, 64)
		if err != nil {
			c.errorf("error pasing opentsdb major version number %v: %v", sp[0], err)
		}
		minor, err := strconv.ParseInt(sp[1], 10, 64)
		if err != nil {
			c.errorf("error pasing opentsdb minor version number %v: %v", sp[1], err)
		}
		c.TSDBVersion = &opentsdb.Version{Major: major, Minor: minor}
	case "graphiteHost":
		c.GraphiteHost = v
	case "graphiteHeader":
		if !strings.Contains(v, ":") {
			c.errorf("graphiteHeader must be in key:value form")
		}
		c.GraphiteHeaders = append(c.GraphiteHeaders, v)
	case "logstashElasticHosts":
		c.LogstashElasticHosts = strings.Split(v, ",")
	case "elasticHosts":
		c.ElasticHosts = strings.Split(v, ",")
	case "influxHost":
		c.InfluxConfig.URL.Host = v
		c.InfluxConfig.UserAgent = "bosun"
		// Default scheme to non-TLS
		c.InfluxConfig.URL.Scheme = "http"
	case "influxUsername":
		c.InfluxConfig.Username = v
	case "influxPassword":
		c.InfluxConfig.Password = v
	case "influxTLS":
		b, err := strconv.ParseBool(v)
		if err != nil {
			c.error(err)
		}
		if b {
			c.InfluxConfig.URL.Scheme = "https"
		} else {
			c.InfluxConfig.URL.Scheme = "http"
		}
	case "influxTimeout":
		od, err := opentsdb.ParseDuration(v)
		if err != nil {
			c.error(err)
		}
		d := time.Duration(od)
		c.InfluxConfig.Timeout = d
	case "httpListen":
		c.HTTPListen = v
	case "hostname":
		c.Hostname = v
	case "relayListen":
		c.RelayListen = v
	case "smtpHost":
		c.SMTPHost = v
	case "smtpUsername":
		c.SMTPUsername = v
	case "smtpPassword":
		c.SMTPPassword = v
	case "emailFrom":
		c.EmailFrom = v
	case "stateFile":
		c.StateFile = v
	case "ping":
		c.Ping = true
	case "pingDuration":
		d, err := time.ParseDuration(v)
		if err != nil {
			c.errorf(err.Error())
		}
		c.PingDuration = d
	case "noSleep":
		c.NoSleep = true
	case "unknownThreshold":
		i, err := strconv.Atoi(v)
		if err != nil {
			c.error(err)
		}
		c.UnknownThreshold = i
	case "timeAndDate":
		sp := strings.Split(v, ",")
		var t []int
		for _, s := range sp {
			i, err := strconv.Atoi(strings.TrimSpace(s))
			if err != nil {
				c.error(err)
			}
			t = append(t, i)
		}
		c.TimeAndDate = t
	case "responseLimit":
		i, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			c.error(err)
		}
		if i <= 0 {
			c.errorf("responseLimit must be > 0")
		}
		c.ResponseLimit = i
	case "defaultRunEvery":
		var err error
		c.DefaultRunEvery, err = strconv.Atoi(v)
		if err != nil {
			c.error(err)
		}
		if c.DefaultRunEvery <= 0 {
			c.errorf("defaultRunEvery must be > 0")
		}
	case "searchSince":
		s, err := opentsdb.ParseDuration(v)
		if err != nil {
			c.error(err)
		}
		c.SearchSince = s
	case "unknownTemplate":
		c.unknownTemplate = v
		t, ok := c.Templates[c.unknownTemplate]
		if !ok {
			c.errorf("template not found: %s", c.unknownTemplate)
		}
		c.UnknownTemplate = t
	case "squelch":
		c.squelch = append(c.squelch, v)
		if err := c.Squelch.Add(v); err != nil {
			c.error(err)
		}
	case "shortURLKey":
		c.ShortURLKey = v
	case "internetProxy":
		c.InternetProxy = v
	case "ledisDir":
		c.LedisDir = v
	case "ledisBindAddr":
		c.LedisBindAddr = v
	case "redisHost":
		c.RedisHost = v
	case "redisPassword":
		c.RedisPassword = v
	case "redisDb":
		i, err := strconv.Atoi(v)
		if err != nil {
			c.error(err)
		}
		c.RedisDb = i
	case "annotateElasticHosts":
		c.AnnotateElasticHosts = strings.Split(v, ",")
	case "annotationIndex":
		c.AnnotateIndex = v
	case "minGroupSize":
		i, err := strconv.Atoi(v)
		if err != nil {
			c.error(err)
		}
		c.MinGroupSize = i
	default:
		if !strings.HasPrefix(k, "$") {
			c.errorf("unknown key %s", k)
		}
		c.Vars[k] = v
		c.Vars[k[1:]] = c.Vars[k]
	}
}

func (c *Conf) loadSection(s *parse.SectionNode) {
	switch s.SectionType.Text {
	case "template":
		c.loadTemplate(s)
	case "alert":
		c.loadAlert(s)
	case "notification":
		c.loadNotification(s)
	case "macro":
		c.loadMacro(s)
	case "lookup":
		c.loadLookup(s)
	default:
		c.errorf("unknown section type: %s", s.SectionType.Text)
	}
}

func (c *Conf) parseIPs(s string) (nets []*net.IPNet) {
	rawCIDRs := strings.Split(s, ",")
	for _, rc := range rawCIDRs {
		_, ipnet, err := net.ParseCIDR(rc)
		if err != nil {
			c.error(err)
		}
		nets = append(nets, ipnet)
	}
	return nets
}

type nodePair struct {
	node parse.Node
	key  string
	val  string
}

type sectionType int

const (
	sNormal sectionType = iota
	sMacro
)

func (c *Conf) getPairs(s *parse.SectionNode, vars Vars, st sectionType) (pairs []nodePair) {
	saw := make(map[string]bool)
	ignoreBadExpand := st == sMacro
	add := func(n parse.Node, k, v string) {
		c.seen(k, saw)
		if vars != nil && strings.HasPrefix(k, "$") {
			vars[k] = v
			if st != sMacro {
				vars[k[1:]] = v
			}
		} else {
			pairs = append(pairs, nodePair{
				node: n,
				key:  k,
				val:  v,
			})
		}
	}
	for _, n := range s.Nodes.Nodes {
		c.at(n)
		switch n := n.(type) {
		case *parse.PairNode:
			v := c.Expand(n.Val.Text, vars, ignoreBadExpand)
			switch k := n.Key.Text; k {
			case "macro":
				m, ok := c.Macros[v]
				if !ok {
					c.errorf("macro not found: %s", v)
				}
				for _, p := range m.Pairs {
					add(p.node, p.key, c.Expand(p.val, vars, ignoreBadExpand))
				}
			default:
				add(n, k, v)
			}
		default:
			c.errorf("unexpected node")
		}
	}
	return
}

func (c *Conf) loadLookup(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Lookups[name]; ok {
		c.errorf("duplicate lookup name: %s", name)
	}
	l := Lookup{
		Name: name,
	}
	l.Text = s.RawText
	var lookupTags opentsdb.TagSet
	saw := make(map[string]bool)
	for _, n := range s.Nodes.Nodes {
		c.at(n)
		switch n := n.(type) {
		case *parse.SectionNode:
			if n.SectionType.Text != "entry" {
				c.errorf("unexpected subsection type")
			}
			tags, err := opentsdb.ParseTags(n.Name.Text)
			if tags == nil && err != nil {
				c.error(err)
			}
			if _, ok := saw[tags.String()]; ok {
				c.errorf("duplicate entry")
			}
			saw[tags.String()] = true
			if len(tags) == 0 {
				c.errorf("lookup entries require tags")
			}
			empty := make(opentsdb.TagSet)
			for k := range tags {
				empty[k] = ""
			}
			if len(lookupTags) == 0 {
				lookupTags = empty
				for k := range empty {
					l.Tags = append(l.Tags, k)
				}
			} else if !lookupTags.Equal(empty) {
				c.errorf("lookup tags mismatch, expected %v", lookupTags)
			}
			e := Entry{
				Def:  n.RawText,
				Name: n.Name.Text,
				ExprEntry: &ExprEntry{
					AlertKey: models.NewAlertKey("", tags),
					Values:   make(map[string]string),
				},
			}
			for _, en := range n.Nodes.Nodes {
				c.at(en)
				switch en := en.(type) {
				case *parse.PairNode:
					e.Values[en.Key.Text] = en.Val.Text
				default:
					c.errorf("unexpected node")
				}
			}
			l.Entries = append(l.Entries, &e)
		default:
			c.errorf("unexpected node")
		}
	}
	c.at(s)
	c.Lookups[name] = &l
}

func (c *Conf) loadMacro(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Macros[name]; ok {
		c.errorf("duplicate macro name: %s", name)
	}
	m := Macro{
		Name: name,
	}
	m.Text = s.RawText
	pairs := c.getPairs(s, nil, sMacro)
	for _, p := range pairs {
		m.Pairs = append(m.Pairs, p)
	}
	c.at(s)
	c.Macros[name] = &m
}

var defaultFuncs = ttemplate.FuncMap{
	"bytes": func(v interface{}) (ByteSize, error) {
		switch v := v.(type) {
		case string:
			f, err := strconv.ParseFloat(v, 64)
			return ByteSize(f), err
		case int:
			return ByteSize(v), nil
		case float64:
			return ByteSize(v), nil
		case expr.Number:
			return ByteSize(v), nil
		case expr.Scalar:
			return ByteSize(v), nil
		}
		return ByteSize(0), fmt.Errorf("unexpected type: %T (%v)", v, v)
	},
	"pct": func(i interface{}) string {
		return fmt.Sprintf("%.2f%%", i)
	},
	"replace": strings.Replace,
	"short": func(v string) string {
		return strings.SplitN(v, ".", 2)[0]
	},
	"parseDuration": time.ParseDuration,
}

func (c *Conf) loadTemplate(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Templates[name]; ok {
		c.errorf("duplicate template name: %s", name)
	}
	t := Template{
		Vars: make(map[string]string),
		Name: name,
	}
	t.Text = s.RawText
	funcs := ttemplate.FuncMap{
		"V": func(v string) string {
			return c.Expand(v, t.Vars, false)
		},
	}
	saw := make(map[string]bool)
	for _, p := range s.Nodes.Nodes {
		c.at(p)
		switch p := p.(type) {
		case *parse.PairNode:
			c.seen(p.Key.Text, saw)
			v := p.Val.Text
			switch k := p.Key.Text; k {
			case "body":
				t.body = v
				tmpl := c.bodies.New(name).Funcs(htemplate.FuncMap(funcs))
				_, err := tmpl.Parse(t.body)
				if err != nil {
					c.error(err)
				}
				t.Body = tmpl
			case "subject":
				t.subject = v
				tmpl := c.subjects.New(name).Funcs(funcs)
				_, err := tmpl.Parse(t.subject)
				if err != nil {
					c.error(err)
				}
				t.Subject = tmpl
			default:
				if !strings.HasPrefix(k, "$") {
					c.errorf("unknown key %s", k)
				}
				t.Vars[k] = v
				t.Vars[k[1:]] = t.Vars[k]
			}
		default:
			c.errorf("unexpected node")
		}
	}
	c.at(s)
	if t.Body == nil && t.Subject == nil {
		c.errorf("neither body or subject specified")
	}
	c.Templates[name] = &t
}

var lookupNotificationRE = regexp.MustCompile(`^lookup\("(.*)", "(.*)"\)$`)

func (c *Conf) loadAlert(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Alerts[name]; ok {
		c.errorf("duplicate alert name: %s", name)
	}
	a := Alert{
		Vars:             make(map[string]string),
		Name:             name,
		CritNotification: new(Notifications),
		WarnNotification: new(Notifications),
	}
	a.Text = s.RawText
	procNotification := func(v string, ns *Notifications) {
		if lookup := lookupNotificationRE.FindStringSubmatch(v); lookup != nil {
			if ns.Lookups == nil {
				ns.Lookups = make(map[string]*Lookup)
			}
			l := c.Lookups[lookup[1]]
			if l == nil {
				c.errorf("unknown lookup table %s", lookup[1])
			}
			for _, e := range l.Entries {
				for k, v := range e.Values {
					if k != lookup[2] {
						continue
					}
					if _, err := c.parseNotifications(v); err != nil {
						c.errorf("lookup %s: %v", v, err)
					}
				}
			}
			ns.Lookups[lookup[2]] = l
			return
		}
		n, err := c.parseNotifications(v)
		if err != nil {
			c.error(err)
		}
		if ns.Notifications == nil {
			ns.Notifications = make(map[string]*Notification)
		}
		for k, v := range n {
			ns.Notifications[k] = v
		}
	}
	pairs := c.getPairs(s, a.Vars, sNormal)
	for _, p := range pairs {
		c.at(p.node)
		v := p.val
		switch p.key {
		case "template":
			a.template = v
			t, ok := c.Templates[a.template]
			if !ok {
				c.errorf("template not found %s", a.template)
			}
			a.Template = t
		case "crit":
			a.Crit = c.NewExpr(v)
		case "warn":
			a.Warn = c.NewExpr(v)
		case "depends":
			a.Depends = c.NewExpr(v)
		case "squelch":
			a.squelch = append(a.squelch, v)
			if err := a.Squelch.Add(v); err != nil {
				c.error(err)
			}
		case "critNotification":
			procNotification(v, a.CritNotification)
		case "warnNotification":
			procNotification(v, a.WarnNotification)
		case "unknown":
			od, err := opentsdb.ParseDuration(v)
			if err != nil {
				c.error(err)
			}
			d := time.Duration(od)
			if d < time.Second {
				c.errorf("unknown duration must be at least 1s")
			}
			a.Unknown = d
		case "maxLogFrequency":
			od, err := opentsdb.ParseDuration(v)
			if err != nil {
				c.error(err)
			}
			d := time.Duration(od)
			if d < time.Second {
				c.errorf("max log frequency must be at least 1s")
			}
			a.MaxLogFrequency = d
		case "unjoinedOk":
			a.UnjoinedOK = true
		case "ignoreUnknown":
			a.IgnoreUnknown = true
		case "unknownIsNormal":
			a.UnknownsNormal = true
		case "log":
			a.Log = true
		case "runEvery":
			var err error
			a.RunEvery, err = strconv.Atoi(v)
			if err != nil {
				c.error(err)
			}
		default:
			c.errorf("unknown key %s", p.key)
		}
	}
	if a.MaxLogFrequency != 0 && !a.Log {
		c.errorf("maxLogFrequency can only be used on alerts with `log = true`.")
	}
	c.at(s)
	if a.Crit == nil && a.Warn == nil {
		c.errorf("neither crit or warn specified")
	}
	var tags eparse.Tags
	var ret models.FuncType
	if a.Crit != nil {
		ctags, err := a.Crit.Root.Tags()
		if err != nil {
			c.error(err)
		}
		tags = ctags
		ret = a.Crit.Root.Return()
	}
	if a.Warn != nil {
		wtags, err := a.Warn.Root.Tags()
		if err != nil {
			c.error(err)
		}
		wret := a.Warn.Root.Return()
		if a.Crit == nil {
			tags = wtags
			ret = wret
		} else if ret != wret {
			c.errorf("crit and warn expressions must return same type (%v != %v)", ret, wret)
		} else if !tags.Equal(wtags) {
			c.errorf("crit tags (%v) and warn tags (%v) must be equal", tags, wtags)
		}
	}
	if a.Depends != nil {
		depTags, err := a.Depends.Root.Tags()
		if err != nil {
			c.error(err)
		}
		if len(depTags.Intersection(tags)) < 1 {
			c.errorf("Depends and crit/warn must share at least one tag.")
		}
	}
	if a.Log {
		for _, n := range a.CritNotification.Notifications {
			if n.Next != nil {
				c.errorf("cannot use log with a chained notification")
			}
		}
		for _, n := range a.WarnNotification.Notifications {
			if n.Next != nil {
				c.errorf("cannot use log with a chained notification")
			}
		}
		if a.Crit != nil && len(a.CritNotification.Notifications) == 0 {
			c.errorf("log + crit specified, but no critNotification")
		}
		if a.Warn != nil && len(a.WarnNotification.Notifications) == 0 {
			c.errorf("log + warn specified, but no warnNotification")
		}
	}
	if len(a.WarnNotification.Notifications) != 0 {
		if a.Warn == nil {
			c.errorf("warnNotification specified, but no warn")
		}
		if a.Template == nil {
			c.errorf("warnNotification specified, but no template")
		}
	}
	if len(a.CritNotification.Notifications) != 0 {
		if a.Crit == nil {
			c.errorf("critNotification specified, but no crit")
		}
		if a.Template == nil {
			c.errorf("critNotification specified, but no template")
		}
	}
	if a.RunEvery == 0 {
		a.RunEvery = c.DefaultRunEvery
	}
	a.returnType = ret
	c.Alerts[name] = &a
}

func (c *Conf) loadNotification(s *parse.SectionNode) {
	name := s.Name.Text
	if _, ok := c.Notifications[name]; ok {
		c.errorf("duplicate notification name: %s", name)
	}
	n := Notification{
		Vars:         make(map[string]string),
		ContentType:  "application/x-www-form-urlencoded",
		Name:         name,
		RunOnActions: true,
	}
	n.Text = s.RawText
	funcs := ttemplate.FuncMap{
		"V": func(v string) string {
			return c.Expand(v, n.Vars, false)
		},
		"json": func(v interface{}) string {
			b, err := json.Marshal(v)
			if err != nil {
				slog.Errorln(err)
			}
			return string(b)
		},
	}
	c.Notifications[name] = &n
	pairs := c.getPairs(s, n.Vars, sNormal)
	for _, p := range pairs {
		c.at(p.node)
		v := p.val
		switch k := p.key; k {
		case "email":
			if c.SMTPHost == "" || c.EmailFrom == "" {
				c.errorf("email notifications require both smtpHost and emailFrom to be set")
			}
			n.email = v
			email, err := mail.ParseAddressList(n.email)
			if err != nil {
				c.error(err)
			}
			n.Email = email
		case "post":
			n.post = v
			post, err := url.Parse(n.post)
			if err != nil {
				c.error(err)
			}
			n.Post = post
		case "get":
			n.get = v
			get, err := url.Parse(n.get)
			if err != nil {
				c.error(err)
			}
			n.Get = get
		case "print":
			n.Print = true
		case "contentType":
			n.ContentType = v
		case "next":
			n.next = v
			next, ok := c.Notifications[n.next]
			if !ok {
				c.errorf("unknown notification %s", n.next)
			}
			n.Next = next
		case "timeout":
			d, err := opentsdb.ParseDuration(v)
			if err != nil {
				c.error(err)
			}
			n.Timeout = time.Duration(d)
		case "body":
			n.body = v
			tmpl := ttemplate.New(name).Funcs(funcs)
			_, err := tmpl.Parse(n.body)
			if err != nil {
				c.error(err)
			}
			n.Body = tmpl
		case "runOnActions":
			n.RunOnActions = v == "true"
		case "useBody":
			n.UseBody = v == "true"
		default:
			c.errorf("unknown key %s", k)
		}
	}
	c.at(s)
	if n.Timeout > 0 && n.Next == nil {
		c.errorf("timeout specified without next")
	}
}

var exRE = regexp.MustCompile(`\$(?:[\w.]+|\{[\w.]+\})`)

func (c *Conf) Expand(v string, vars map[string]string, ignoreBadExpand bool) string {
	ss := exRE.ReplaceAllStringFunc(v, func(s string) string {
		var n string
		if strings.HasPrefix(s, "${") && strings.HasSuffix(s, "}") {
			s = "$" + s[2:len(s)-1]
		}
		if _n, ok := vars[s]; ok {
			n = _n
		} else if _n, ok := c.Vars[s]; ok {
			n = _n
		} else if strings.HasPrefix(s, "$env.") {
			n = os.Getenv(s[5:])
		} else if ignoreBadExpand {
			return s
		} else {
			c.errorf("unknown variable %s", s)
		}
		return c.Expand(n, vars, ignoreBadExpand)
	})
	return ss
}

func (c *Conf) seen(v string, m map[string]bool) {
	if m[v] {
		switch v {
		case "squelch", "critNotification", "warnNotification", "graphiteHeader":
			// ignore
		default:
			c.errorf("duplicate key: %s", v)
		}
	}
	m[v] = true
}

var builtins = htemplate.FuncMap{
	"and":      nilFunc,
	"call":     nilFunc,
	"html":     nilFunc,
	"index":    nilFunc,
	"js":       nilFunc,
	"len":      nilFunc,
	"not":      nilFunc,
	"or":       nilFunc,
	"print":    nilFunc,
	"printf":   nilFunc,
	"println":  nilFunc,
	"urlquery": nilFunc,
	"eq":       nilFunc,
	"ge":       nilFunc,
	"gt":       nilFunc,
	"le":       nilFunc,
	"lt":       nilFunc,
	"ne":       nilFunc,

	// HTML-specific funcs
	"html_template_attrescaper":     nilFunc,
	"html_template_commentescaper":  nilFunc,
	"html_template_cssescaper":      nilFunc,
	"html_template_cssvaluefilter":  nilFunc,
	"html_template_htmlnamefilter":  nilFunc,
	"html_template_htmlescaper":     nilFunc,
	"html_template_jsregexpescaper": nilFunc,
	"html_template_jsstrescaper":    nilFunc,
	"html_template_jsvalescaper":    nilFunc,
	"html_template_nospaceescaper":  nilFunc,
	"html_template_rcdataescaper":   nilFunc,
	"html_template_urlescaper":      nilFunc,
	"html_template_urlfilter":       nilFunc,
	"html_template_urlnormalizer":   nilFunc,

	// bosun-specific funcs
	"V":       nilFunc,
	"bytes":   nilFunc,
	"replace": nilFunc,
	"short":   nilFunc,
}

func nilFunc() {}

func (c *Conf) NewExpr(s string) *expr.Expr {
	exp, err := expr.New(s, c.Funcs())
	if err != nil {
		c.error(err)
	}
	switch exp.Root.Return() {
	case models.TypeNumberSet, models.TypeScalar:
		break
	default:
		c.errorf("expression must return a number")
	}
	return exp
}

func (c *Conf) Funcs() map[string]eparse.Func {
	lookup := func(e *expr.State, T miniprofiler.Timer, lookup, key string) (results *expr.Results, err error) {
		results = new(expr.Results)
		results.IgnoreUnjoined = true
		l := c.Lookups[lookup]
		if l == nil {
			return nil, fmt.Errorf("lookup table not found: %v", lookup)
		}
		lookups := l.ToExpr()
		if lookups == nil {
			err = fmt.Errorf("lookup table not found: %v", lookup)
			return
		}
		var tags []opentsdb.TagSet
		for _, tag := range lookups.Tags {
			var next []opentsdb.TagSet
			vals, err := e.Search.TagValuesByTagKey(tag, 0)
			if err != nil {
				return nil, err
			}
			for _, value := range vals {
				for _, s := range tags {
					t := s.Copy()
					t[tag] = value
					next = append(next, t)
				}
				if len(tags) == 0 {
					next = append(next, opentsdb.TagSet{tag: value})
				}
			}
			tags = next
		}
		for _, tag := range tags {
			value, ok := lookups.Get(key, tag)
			if !ok {
				continue
			}
			var num float64
			num, err = strconv.ParseFloat(value, 64)
			if err != nil {
				return nil, err
			}
			results.Results = append(results.Results, &expr.Result{
				Value: expr.Number(num),
				Group: tag,
			})
		}
		return results, nil
	}
	lookupSeries := func(e *expr.State, T miniprofiler.Timer, series *expr.Results, lookup, key string) (results *expr.Results, err error) {
		results = new(expr.Results)
		results.IgnoreUnjoined = true
		l := c.Lookups[lookup]
		if l == nil {
			return nil, fmt.Errorf("lookup table not found: %v", lookup)
		}
		lookups := l.ToExpr()
		if lookups == nil {
			err = fmt.Errorf("lookup table not found: %v", lookup)
			return
		}
		for _, res := range series.Results {
			value, ok := lookups.Get(key, res.Group)
			if !ok {
				continue
			}
			var num float64
			num, err = strconv.ParseFloat(value, 64)
			if err != nil {
				return nil, err
			}
			results.Results = append(results.Results, &expr.Result{
				Value: expr.Number(num),
				Group: res.Group,
			})
		}
		return results, nil
	}
	lookupTags := func(args []eparse.Node) (eparse.Tags, error) {
		name := args[0].(*eparse.StringNode).Text
		lookup := c.Lookups[name]
		if lookup == nil {
			return nil, fmt.Errorf("bad lookup table %v", name)
		}
		t := make(eparse.Tags)
		for _, v := range lookup.Tags {
			t[v] = struct{}{}
		}
		return t, nil
	}
	lookupSeriesTags := func(args []eparse.Node) (eparse.Tags, error) {
		name := args[1].(*eparse.StringNode).Text
		lookup := c.Lookups[name]
		if lookup == nil {
			return nil, fmt.Errorf("bad lookup table %v", name)
		}
		t := make(eparse.Tags)
		for _, v := range lookup.Tags {
			t[v] = struct{}{}
		}
		return t, nil
	}

	tagAlert := func(args []eparse.Node) (eparse.Tags, error) {
		name := args[0].(*eparse.StringNode).Text
		key := args[1].(*eparse.StringNode).Text
		a, e, err := c.getAlertExpr(name, key)
		if err != nil {
			return nil, err
		}
		if a.returnType != models.TypeNumberSet {
			return nil, fmt.Errorf("alert requires a number-returning expression (got %v)", a.returnType)
		}
		return e.Root.Tags()
	}

	funcs := map[string]eparse.Func{
		"alert": {
			Args:   []models.FuncType{models.TypeString, models.TypeString},
			Return: models.TypeNumberSet,
			Tags:   tagAlert,
			F:      c.alert,
		},
		"lookup": {
			Args:   []models.FuncType{models.TypeString, models.TypeString},
			Return: models.TypeNumberSet,
			Tags:   lookupTags,
			F:      lookup,
		},
		"lookupSeries": {
			Args:   []models.FuncType{models.TypeSeriesSet, models.TypeString, models.TypeString},
			Return: models.TypeNumberSet,
			Tags:   lookupSeriesTags,
			F:      lookupSeries,
		},
	}
	merge := func(fs map[string]eparse.Func) {
		for k, v := range fs {
			funcs[k] = v
		}
	}
	if c.TSDBHost != "" {
		merge(expr.TSDB)
	}
	if c.GraphiteHost != "" {
		merge(expr.Graphite)
	}
	if len(c.LogstashElasticHosts) != 0 {
		merge(expr.LogstashElastic)
	}
	if len(c.ElasticHosts) != 0 {
		merge(expr.Elastic)
	}
	if c.InfluxConfig.URL.Host != "" {
		merge(expr.Influx)
	}
	return funcs
}

func (c *Conf) getAlertExpr(name, key string) (*Alert, *expr.Expr, error) {
	a := c.Alerts[name]
	if a == nil {
		return nil, nil, fmt.Errorf("bad alert name %v", name)
	}
	var e *expr.Expr
	switch key {
	case "crit":
		e = a.Crit
	case "warn":
		e = a.Warn
	default:
		return nil, nil, fmt.Errorf("alert: unsupported key %v", key)
	}
	if e == nil {
		return nil, nil, fmt.Errorf("alert: nil expression")
	}
	return a, e, nil
}

func (c *Conf) alert(s *expr.State, T miniprofiler.Timer, name, key string) (results *expr.Results, err error) {
	_, e, err := c.getAlertExpr(name, key)
	if err != nil {
		return nil, err
	}
	results, _, err = e.ExecuteState(s, T)
	if err != nil {
		return nil, err
	}
	if s.History != nil {
		unknownTags, unevalTags := s.History.GetUnknownAndUnevaluatedAlertKeys(name)
		// For currently unknown tags NOT in the result set, add an error result
		for _, ak := range unknownTags {
			found := false
			for _, result := range results.Results {
				if result.Group.Equal(ak.Group()) {
					found = true
					break
				}
			}
			if !found {
				res := expr.Result{
					Value: expr.Number(1),
					Group: ak.Group(),
				}
				results.Results = append(results.Results, &res)
			}
		}
		//For all unevaluated tags in run history, make sure we report a nonzero result.
		for _, ak := range unevalTags {
			found := false
			for _, result := range results.Results {
				if result.Group.Equal(ak.Group()) {
					result.Value = expr.Number(1)
					found = true
					break
				}
			}
			if !found {
				res := expr.Result{
					Value: expr.Number(1),
					Group: ak.Group(),
				}
				results.Results = append(results.Results, &res)
			}
		}
	}
	return results, nil
}

func (c *Conf) MakeLink(path string, v *url.Values) string {
	u := url.URL{
		Scheme:   "http",
		Host:     c.Hostname,
		Path:     path,
		RawQuery: v.Encode(),
	}
	return u.String()
}


text:
@interface GifCollectionViewController ()

@end

@implementation GifCollectionViewController

static NSString * const reuseIdentifier = @"Cell";

- (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = NO;
    __weak typeof(self)weakSelf = self;
//    self.collectionView.backgroundColor = [UIColor colorWithRed:41/255.0 green:68/255.0 blue:119/255.0 alpha:1.0];
    self.collectionView.backgroundColor = [UIColor whiteColor];
    // Register cell classes
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
    NSString *url =  [[NSBundle mainBundle] pathForResource:@"giphy.gif" ofType:nil];
    NSData *data = [NSData dataWithContentsOfFile:url];
    self.collectionView.sy_header = [SYGifHeaderFooter headerWithData:data orientation:SYRefreshViewOrientationLeft isBig:NO height:100 callBack:^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf.collectionView.sy_header endRefreshing];
            NSLog(@"刷新结束");
        });
    }];
    [self.collectionView.sy_header beginRefreshing];

    self.collectionView.sy_footer = [SYGifHeaderFooter headerWithData:data orientation:SYRefreshViewOrientationRight isBig:NO height:100 callBack:^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf.collectionView.sy_footer endRefreshing];
            NSLog(@"刷新结束");
        });
    }];
    [self.collectionView.sy_footer beginRefreshing];
}

#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 100;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
    cell.contentView.backgroundColor = [UIColor grayColor];
    return cell;
}

@end

redpajama_set_name: RedPajamaGithub


text:
package com.facebook.react.bridge;

import java.util.Map;

/**
 * A native module whose API can be provided to JS catalyst instances.  {@link NativeModule}s whose
 * implementation is written in Java should extend {@link BaseJavaModule} or {@link
 * ReactContextBaseJavaModule}.  {@link NativeModule}s whose implementation is written in C++
 * must not provide any Java code (so they can be reused on other platforms), and instead should
 * register themselves using {@link CxxModuleWrapper}.
 */
public interface NativeModule {
  interface NativeMethod {
    void invoke(JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray parameters);
    String getType();
  }

  /**
   * @return the name of this module. This will be the name used to {@code require()} this module
   * from javascript.
   */
  String getName();

  /**
   * @return methods callable from JS on this module
   */
  Map<String, NativeMethod> getMethods();

  /**
   * This is called at the end of {@link CatalystApplicationFragment#createCatalystInstance()}
   * after the CatalystInstance has been created, in order to initialize NativeModules that require
   * the CatalystInstance or JS modules.
   */
  void initialize();

  /**
   * Return true if you intend to override some other native module that was registered e.g. as part
   * of a different package (such as the core one). Trying to override without returning true from
   * this method is considered an error and will throw an exception during initialization. By
   * default all modules return false.
   */
  boolean canOverrideExistingModule();

  /**
   * Called before {CatalystInstance#onHostDestroy}
   */
  void onCatalystInstanceDestroy();

  /**
   * In order to support web workers, a module must be aware that it can be invoked from multiple
   * different JS VMs. Supporting web workers means recognizing things like:
   *
   * 1) ids (e.g. timer ids, request ids, etc.) may only unique on a per-VM basis
   * 2) the module needs to make sure to enqueue callbacks and JS module calls to the correct VM
   *
   * In order to facilitate this, modules that support web workers will have all their @ReactMethod-
   * annotated methods passed a {@link ExecutorToken} as the first parameter before any arguments
   * from JS. This ExecutorToken internally maps to a specific JS VM and can be used by the
   * framework to route calls appropriately. In order to make JS module calls correctly, start using
   * the version of {@link ReactContext#getJSModule(ExecutorToken, Class)} that takes an
   * ExecutorToken. It will ensure that any calls you dispatch to the returned object will go to
   * the right VM. For Callbacks, you don't have to do anything special -- the framework
   * automatically tags them with the correct ExecutorToken when the are created.
   *
   * Note: even though calls can come from multiple JS VMs on multiple threads, calls to this module
   * will still only occur on a single thread.
   *
   * @return whether this module supports web workers.
   */
  boolean supportsWebWorkers();
}


text:
{-# OPTIONS -fglasgow-exts #-}
-----------------------------------------------------------------------------
{-| Module    : Script.hs
    Copyright : (c) David Harley 2010
    Project   : qtHaskell
    Version   : 1.1.4
    Modified  : 2010-09-02 17:02:34

    Warning   : this file is machine generated - do not modify.
--}
-----------------------------------------------------------------------------

module Qtc.Classes.Script (
  qScriptEngine, evaluate, newObject, globalObject, newQObject, newQMetaObject, toScriptValue, fromScriptValue, toScriptQObjectValue, fromScriptQObjectValue
  , construct, call, setScriptProperty, scriptProperty, qScriptValue_delete
  , toScriptInt, toBool, toScriptString
  , fromScriptInt, fromBool, fromScriptString
  , argument, argumentCount, thisObject, qScriptContext_delete
  , qNsfContainer
  , registerDsSignal, dsSignal_nll, dsSignal_int, dsSignal_bool, dsSignal_ptr, connectDynamic, connectDynamicSlot
  , scriptSlot_nll, scriptSlot_int, scriptSlot_bool, scriptSlot_ptr
  )
  where

import Qtc.Classes.Base
import Qtc.ClassTypes.Core
import Qtc.Core.Base
import Qtc.ClassTypes.Script
import Data.List

class QqScriptEngine x1 where
  qScriptEngine :: x1 -> IO (QScriptEngine ())

instance QqScriptEngine (()) where
 qScriptEngine ()
  = withQScriptEngineResult $
    qtc_QScriptEngine

foreign import ccall "qtc_QScriptEngine" qtc_QScriptEngine :: IO (Ptr (TQScriptEngine ()))

instance QqScriptEngine ((QObject a)) where
 qScriptEngine _qobj
  = withQScriptEngineResult $
    withObjectPtr _qobj $ \cobj_qobj ->
    qtc_QScriptEngine1 cobj_qobj

foreign import ccall "qtc_QScriptEngine1" qtc_QScriptEngine1 :: Ptr (TQObject a) -> IO (Ptr (TQScriptEngine ()))

evaluate :: QScriptEngine a -> String -> IO (QScriptValue ())
evaluate _qsce _sdat
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    withCWString _sdat $ \cstr_sdat ->
    qtc_QScriptEngine_evaluate cobj_qsce cstr_sdat

foreign import ccall "qtc_QScriptEngine_evaluate" qtc_QScriptEngine_evaluate :: Ptr (TQScriptEngine a) -> CWString -> IO (Ptr (TQScriptValue ()))

newObject :: QScriptEngine a -> IO (QScriptValue ())
newObject _qsce
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    qtc_QScriptEngine_newObject cobj_qsce

foreign import ccall "qtc_QScriptEngine_newObject" qtc_QScriptEngine_newObject :: Ptr (TQScriptEngine a) -> IO (Ptr (TQScriptValue ()))

globalObject :: QScriptEngine a -> IO (QScriptValue ())
globalObject _qsce
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    qtc_QScriptEngine_globalObject cobj_qsce

foreign import ccall "qtc_QScriptEngine_globalObject" qtc_QScriptEngine_globalObject :: Ptr (TQScriptEngine a) -> IO (Ptr (TQScriptValue ()))

newQObject :: QScriptEngine a -> QObject b -> IO (QScriptValue ())
newQObject _qsce _qobj
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qobj $ \cobj_qobj ->
    qtc_QScriptEngine_newQObject cobj_qsce cobj_qobj

foreign import ccall "qtc_QScriptEngine_newQObject" qtc_QScriptEngine_newQObject :: Ptr (TQScriptEngine a) -> Ptr (TQObject b) -> IO (Ptr (TQScriptValue ()))

newQMetaObject :: QScriptEngine a -> QMetaObject b -> IO (QScriptValue ())
newQMetaObject _qsce _qobj
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qobj $ \cobj_qobj ->
    qtc_QScriptEngine_newQMetaObject cobj_qsce cobj_qobj

foreign import ccall "qtc_QScriptEngine_newQMetaObject" qtc_QScriptEngine_newQMetaObject :: Ptr (TQScriptEngine a) -> Ptr (TQMetaObject b) -> IO (Ptr (TQScriptValue ()))

toScriptValue :: String -> QScriptEngine a -> Object b -> IO (QScriptValue ())
toScriptValue _qtyp _qsce _qobj
  = withQScriptValueResult $
    withCWString _qtyp $ \cstr_qtyp ->
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qobj $ \cobj_qobj ->
    qtc_QScriptEngine_toScriptValue cstr_qtyp cobj_qsce cobj_qobj

foreign import ccall "qtc_QScriptEngine_toScriptValue" qtc_QScriptEngine_toScriptValue :: CWString -> Ptr (TQScriptEngine a) -> Ptr b -> IO (Ptr (TQScriptValue ()))

toScriptQObjectValue :: String -> QScriptEngine a -> QObject b -> IO (QScriptValue ())
toScriptQObjectValue _qtyp _qsce _qobj
  = withQScriptValueResult $
    withCWString _qtyp $ \cstr_qtyp ->
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qobj $ \cobj_qobj ->
    qtc_QScriptEngine_toScriptQObjectValue cstr_qtyp cobj_qsce cobj_qobj

foreign import ccall "qtc_QScriptEngine_toScriptQObjectValue" qtc_QScriptEngine_toScriptQObjectValue :: CWString -> Ptr (TQScriptEngine a) -> Ptr (TQObject b) -> IO (Ptr (TQScriptValue ()))

fromScriptValue :: String -> QScriptEngine a -> QScriptValue () -> IO (Object ())
fromScriptValue _qtyp _qsce _qscv
  = withObjectRefResult $
    withCWString _qtyp $ \cstr_qtyp ->
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qscv $ \cobj_qscv ->
    qtc_QScriptEngine_fromScriptValue cstr_qtyp cobj_qsce cobj_qscv

foreign import ccall "qtc_QScriptEngine_fromScriptValue" qtc_QScriptEngine_fromScriptValue :: CWString -> Ptr (TQScriptEngine a) -> Ptr (TQScriptValue b) -> IO (Ptr ())

fromScriptQObjectValue :: String -> QScriptEngine a -> QScriptValue () -> IO (QObject ())
fromScriptQObjectValue _qtyp _qsce _qscv
  = withQObjectResult $
    withCWString _qtyp $ \cstr_qtyp ->
    withObjectPtr _qsce $ \cobj_qsce ->
    withObjectPtr _qscv $ \cobj_qscv ->
    qtc_QScriptEngine_fromScriptQObjectValue cstr_qtyp cobj_qsce cobj_qscv

foreign import ccall "qtc_QScriptEngine_fromScriptQObjectValue" qtc_QScriptEngine_fromScriptQObjectValue :: CWString -> Ptr (TQScriptEngine a) -> Ptr (TQScriptValue b) -> IO (Ptr (TQObject ()))

construct :: QScriptValue () -> [QScriptValue ()] -> IO (QScriptValue ())
construct _qsvl _qsva
  = withQScriptValueResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    withQListObject _qsva $ \cqlistlen_qsva cqlistobj_qsva ->
    qtc_QScriptValue_construct cobj_qsvl cqlistlen_qsva cqlistobj_qsva

foreign import ccall "qtc_QScriptValue_construct" qtc_QScriptValue_construct :: Ptr (TQScriptValue ()) -> CInt -> Ptr (Ptr (TQScriptValue ())) -> IO (Ptr (TQScriptValue ()))

call :: QScriptValue () -> QScriptValue () -> [QScriptValue ()] -> IO (QScriptValue ())
call _qsvl _qsvt _qsva
  = withQScriptValueResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    withObjectPtr _qsvt $ \cobj_qsvt ->
    withQListObject _qsva $ \cqlistlen_qsva cqlistobj_qsva ->
    qtc_QScriptValue_call cobj_qsvl cobj_qsvt cqlistlen_qsva cqlistobj_qsva

foreign import ccall "qtc_QScriptValue_call" qtc_QScriptValue_call :: Ptr (TQScriptValue ()) -> Ptr (TQScriptValue ()) -> CInt -> Ptr (Ptr (TQScriptValue ())) -> IO (Ptr (TQScriptValue ()))

setScriptProperty :: QScriptValue () -> String -> QScriptValue () -> IO ()
setScriptProperty _qsvl _sprp _qstv
  = withObjectPtr _qsvl $ \cobj_qsvl ->
    withCWString _sprp $ \cstr_sprp ->
    withObjectPtr _qstv $ \cobj_qstv ->
    qtc_QScriptValue_setProperty cobj_qsvl cstr_sprp cobj_qstv

foreign import ccall "qtc_QScriptValue_setProperty" qtc_QScriptValue_setProperty :: Ptr (TQScriptValue ()) -> CWString -> Ptr (TQScriptValue ()) -> IO ()

scriptProperty :: QScriptValue () -> String -> IO (QScriptValue ())
scriptProperty _qsvl _sprp
  = withQScriptValueResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    withCWString _sprp $ \cstr_sprp ->
    qtc_QScriptValue_property cobj_qsvl cstr_sprp

foreign import ccall "qtc_QScriptValue_property" qtc_QScriptValue_property :: Ptr (TQScriptValue ()) -> CWString -> IO (Ptr (TQScriptValue ()))

qScriptValue_delete :: QScriptValue () -> IO ()
qScriptValue_delete _qsvl
  = withObjectPtr _qsvl $ \cobj_qsvl ->
    qtc_QScriptValue_delete cobj_qsvl

foreign import ccall "qtc_QScriptValue_delete" qtc_QScriptValue_delete :: Ptr (TQScriptValue ()) -> IO ()

toScriptInt :: QScriptValue () -> IO (Int)
toScriptInt _qsvl
  = withIntResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    qtc_QScriptValue_toInt cobj_qsvl

foreign import ccall "qtc_QScriptValue_toInt" qtc_QScriptValue_toInt :: Ptr (TQScriptValue ()) -> IO (CInt)

toBool :: QScriptValue () -> IO (Bool)
toBool _qsvl
  = withBoolResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    qtc_QScriptValue_toBool cobj_qsvl

foreign import ccall "qtc_QScriptValue_toBool" qtc_QScriptValue_toBool :: Ptr (TQScriptValue ()) -> IO (CBool)

toScriptString :: QScriptValue () -> IO (String)
toScriptString _qsvl
  = withStringResult $
    withObjectPtr _qsvl $ \cobj_qsvl ->
    qtc_QScriptValue_toString cobj_qsvl
foreign import ccall "qtc_QScriptValue_toString" qtc_QScriptValue_toString :: Ptr (TQScriptValue ()) -> IO (Ptr (TQString ()))

fromScriptInt :: QScriptEngine () -> Int -> IO (QScriptValue ())
fromScriptInt _qsce _aind
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    qtc_QScriptValue_fromInt cobj_qsce (toCInt _aind)

foreign import ccall "qtc_QScriptValue_fromInt" qtc_QScriptValue_fromInt :: Ptr (TQScriptEngine ()) -> CInt -> IO (Ptr (TQScriptValue ()))

fromBool :: QScriptEngine () -> Bool -> IO (QScriptValue ())
fromBool _qsce _abool
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    qtc_QScriptValue_fromBool cobj_qsce (toCBool _abool)

foreign import ccall "qtc_QScriptValue_fromBool" qtc_QScriptValue_fromBool :: Ptr (TQScriptEngine ()) -> CBool -> IO (Ptr (TQScriptValue ()))

fromScriptString :: QScriptEngine () -> String -> IO (QScriptValue ())
fromScriptString _qsce _astr
  = withQScriptValueResult $
    withObjectPtr _qsce $ \cobj_qsce ->
    withCWString _astr $ \cstr_a ->
    qtc_QScriptValue_fromString cobj_qsce cstr_a

foreign import ccall "qtc_QScriptValue_fromString" qtc_QScriptValue_fromString :: Ptr (TQScriptEngine ()) -> CWString -> IO (Ptr (TQScriptValue ()))

argumentCount :: QScriptContext () -> IO (Int)
argumentCount _qctx
  = withIntResult $
    withObjectPtr _qctx $ \cobj_qctx ->
    qtc_QScriptContext_argumentCount cobj_qctx

foreign import ccall "qtc_QScriptContext_argumentCount" qtc_QScriptContext_argumentCount :: Ptr (TQScriptContext ()) -> IO (CInt)

argument :: QScriptContext () -> Int -> IO (QScriptValue ())
argument _qctx _aind
  = withQScriptValueResult $
    withObjectPtr _qctx $ \cobj_qctx ->
    qtc_QScriptContext_argument cobj_qctx (toCInt _aind)

foreign import ccall "qtc_QScriptContext_argument" qtc_QScriptContext_argument :: Ptr (TQScriptContext ()) -> CInt -> IO (Ptr (TQScriptValue ()))

thisObject :: QScriptContext () -> IO (QScriptValue ())
thisObject _qctx
  = withQScriptValueResult $
    withObjectPtr _qctx $ \cobj_qctx ->
    qtc_QScriptContext_thisObject cobj_qctx

foreign import ccall "qtc_QScriptContext_thisObject" qtc_QScriptContext_thisObject :: Ptr (TQScriptContext ()) -> IO (Ptr (TQScriptValue ()))

qScriptContext_delete :: QScriptContext () -> IO ()
qScriptContext_delete _qctx
  = withObjectPtr _qctx $ \cobj_qctx ->
    qtc_QScriptContext_delete cobj_qctx

foreign import ccall "qtc_QScriptContext_delete" qtc_QScriptContext_delete :: Ptr (TQScriptContext ()) -> IO ()

class QqNsfContainer x1 where
  qNsfContainer :: x1 -> IO (QNsfContainer ())

instance QqNsfContainer ((QScriptContext () -> IO ())) where
 qNsfContainer (_qnsf)
  = do
    funptr  <- wrapNsfHandler2 nsfHandlerWrapper2
    stptr   <- newStablePtr (Wrap _qnsf)
    withQNsfContainerResult $
      qtc_QNsfContainer (toCFunPtr funptr) (castStablePtrToPtr stptr)
  where
    nsfHandlerWrapper2 :: Ptr fun -> Ptr () -> Ptr (TQScriptContext ()) -> IO ()
    nsfHandlerWrapper2 funptr stptr x0
      = do x0obj <- objectFromPtr_nf x0
           if (objectIsNull x0obj)
            then do when (stptr/=ptrNull)
                     (freeStablePtr (castPtrToStablePtr stptr))
                    when (funptr/=ptrNull)
                     (freeHaskellFunPtr (castPtrToFunPtr funptr))
            else _qnsf x0obj
           return ()

foreign import ccall "qtc_QNsfContainer" qtc_QNsfContainer :: Ptr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> Ptr () -> IO (Ptr (TQNsfContainer ()))

foreign import ccall "wrapper" wrapNsfHandler2 :: (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> IO (FunPtr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()))

instance QqNsfContainer (QObject a, (QScriptContext () -> IO ())) where
 qNsfContainer (_parent, _qnsf)
  = do
    funptr  <- wrapNsfHandler3 nsfHandlerWrapper3
    stptr   <- newStablePtr (Wrap _qnsf)
    withQNsfContainerResult $
      withObjectPtr _parent $ \cobj_parent ->
      qtc_QNsfContainer1 cobj_parent (toCFunPtr funptr) (castStablePtrToPtr stptr)
  where
    nsfHandlerWrapper3 :: Ptr fun -> Ptr () -> Ptr (TQScriptContext ()) -> IO ()
    nsfHandlerWrapper3 funptr stptr x0
      = do x0obj <- objectFromPtr_nf x0
           if (objectIsNull x0obj)
            then do when (stptr/=ptrNull)
                     (freeStablePtr (castPtrToStablePtr stptr))
                    when (funptr/=ptrNull)
                     (freeHaskellFunPtr (castPtrToFunPtr funptr))
            else _qnsf x0obj
           return ()

foreign import ccall "qtc_QNsfContainer1" qtc_QNsfContainer1 :: Ptr (TQObject a) -> Ptr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> Ptr () -> IO (Ptr (TQNsfContainer ()))

foreign import ccall "wrapper" wrapNsfHandler3 :: (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> IO (FunPtr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()))

instance QqNsfContainer (QObject a, String, (QScriptContext () -> IO ())) where
 qNsfContainer (_parent, _cnam, _qnsf)
  = do
    funptr  <- wrapNsfHandler4 nsfHandlerWrapper4
    stptr   <- newStablePtr (Wrap _qnsf)
    withQNsfContainerResult $
      withObjectPtr _parent $ \cobj_parent ->
      withCWString _cnam $ \cstr_cnam ->
      qtc_QNsfContainer2 cobj_parent cstr_cnam (toCFunPtr funptr) (castStablePtrToPtr stptr)
  where
    nsfHandlerWrapper4 :: Ptr fun -> Ptr () -> Ptr (TQScriptContext ()) -> IO ()
    nsfHandlerWrapper4 funptr stptr x0
      = do x0obj <- objectFromPtr_nf x0
           if (objectIsNull x0obj)
            then do when (stptr/=ptrNull)
                     (freeStablePtr (castPtrToStablePtr stptr))
                    when (funptr/=ptrNull)
                     (freeHaskellFunPtr (castPtrToFunPtr funptr))
            else _qnsf x0obj
           return ()

foreign import ccall "qtc_QNsfContainer2" qtc_QNsfContainer2 :: Ptr (TQObject a) -> CWString -> Ptr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> Ptr () -> IO (Ptr (TQNsfContainer ()))

foreign import ccall "wrapper" wrapNsfHandler4 :: (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()) -> IO (FunPtr (Ptr fun -> Ptr state -> Ptr (TQScriptContext ()) -> IO ()))

registerDsSignal :: QObject a -> QScriptEngine () -> QObject b -> String -> IO ()
registerDsSignal  _this _eng _dom _sig
  | isSuffixOf "()" _sig
   = do
     let nam = take ((length _sig) - 2) _sig
     qNsfContainer (_dom, nam, dsSignal_nll _this _sig)
     return ()
  | isSuffixOf "(int)" _sig
   = do
     let nam = take ((length _sig) - 5) _sig
     qNsfContainer (_dom, nam, dsSignal_int _this _sig)
     return ()
  | isSuffixOf "(bool)" _sig
   = do
     let nam = take ((length _sig) - 6) _sig
     qNsfContainer (_dom, nam, dsSignal_bool _this _sig)
     return ()
  | isPtrSuffix _sig
   = do
     let nam = take ((length _sig) - 7) _sig
     qNsfContainer (_dom, nam, dsSignal_ptr _this _eng _sig)
     return ()
  | otherwise
   = return ()

dsSignal_nll :: QObject a -> String -> QScriptContext () -> IO ()
dsSignal_nll _this _sig _ctx
  = emitSignal _this _sig ()

dsSignal_int :: QObject a -> String -> QScriptContext () -> IO ()
dsSignal_int _this _sig _ctx
  = emitSignal _this _sig =<< toScriptInt =<< argument _ctx 0

dsSignal_bool :: QObject a -> String -> QScriptContext () -> IO ()
dsSignal_bool _this _sig _ctx
  = emitSignal _this _sig =<< toBool =<< argument _ctx 0

dsSignal_ptr :: QObject a -> QScriptEngine () -> String -> QScriptContext () -> IO ()
dsSignal_ptr _this _eng _sig _ctx
  = do
    ptr <- fromScriptValue (getSigPtrTyp _sig) _eng =<< argument _ctx 0
    emitSignal _this _sig ptr

connectDynamic :: QObject a -> QScriptEngine () -> QScriptContext () -> IO ()
connectDynamic _this _eng _ctx
  = do
    sfv <- argument _ctx 3
    stv <- argument _ctx 1
    sig_nam <- toScriptString =<< argument _ctx 0
    slt_nam <- toScriptString =<< argument _ctx 2
    connectDynamicSlot _this _eng sig_nam slt_nam sfv stv

connectDynamicSlot :: QObject a -> QScriptEngine () -> String -> String -> QScriptValue () -> QScriptValue () -> IO ()
connectDynamicSlot _this _eng _sig_nam _slt_nam _sfv _stv
  | (isSuffixOf "()" _sig_nam) && (isSuffixOf "()" _slt_nam)
    = connectSlot _this _sig_nam _this _slt_nam $ scriptSlot_nll _eng _sfv _stv
  | (isSuffixOf "(int)" _sig_nam) && (isSuffixOf "(int)" _slt_nam)
    = connectSlot _this _sig_nam _this _slt_nam $ scriptSlot_int _eng _sfv _stv
  | (isSuffixOf "(bool)" _sig_nam) && (isSuffixOf "(bool)" _slt_nam)
    = connectSlot _this _sig_nam _this _slt_nam $ scriptSlot_bool _eng _sfv _stv
  | (isPtrSuffix _sig_nam) && (isPtrSuffix _slt_nam)
    = connectSlot _this _sig_nam _this _slt_nam $ scriptSlot_ptr _eng _sfv _stv $ getSigPtrTyp _sig_nam
  | otherwise
    = return ()

scriptSlot_nll :: QScriptEngine() -> QScriptValue () -> QScriptValue () -> QObject () -> IO ()
scriptSlot_nll _eng _sfv _stv _this
  = do
    rfv <- call _sfv _stv []
    return ()

scriptSlot_int :: QScriptEngine() -> QScriptValue () -> QScriptValue () -> QObject () -> Int -> IO ()
scriptSlot_int _eng _sfv _stv _this _int
  = do
    dso <- fromScriptInt _eng _int
    rfv <- call _sfv _stv [dso]
    return ()

scriptSlot_bool :: QScriptEngine() -> QScriptValue () -> QScriptValue () -> QObject () -> Bool -> IO ()
scriptSlot_bool _eng _sfv _stv _this _bool
  = do
    dso <- fromBool _eng _bool
    rfv <- call _sfv _stv [dso]
    return ()

scriptSlot_ptr :: QScriptEngine() -> QScriptValue () -> QScriptValue () -> String -> QObject () -> Object a -> IO ()
scriptSlot_ptr _eng _sfv _stv _spt _this _ptr
  = do
    dso <- toScriptValue _spt _eng _ptr
    rfv <- call _sfv _stv [dso]
    return ()

isPtrSuffix :: String -> Bool
isPtrSuffix sig
  = if (t1 == [])
     then False
     else
      if (((last t1) == ')') && ((last (init t1)) == '*'))
       then True
       else False
  where
    t1 = dropWhile ('('/=) sig

getSigPtrTyp :: String -> String
getSigPtrTyp sig
   = "<" ++ (init $ tail $ dropWhile ('('/=) sig) ++ ">"


text:
BEGIN_HYPERDEX_NAMESPACE

class schema
{
    public:
        schema();

    public:
        uint16_t lookup_attr(const char* name) const;

    public:
        uint16_t attrs_sz;
        const attribute* attrs;
};

END_HYPERDEX_NAMESPACE

#endif // hyperdex_common_schema_h_


text:
import quex.engine.analyzer.transition_map              as transition_map_tools
import quex.engine.generator.state.transition.code      as transition_code
import quex.engine.generator.state.transition.solution  as solution
import quex.engine.generator.state.transition.bisection as bisection
from   quex.engine.interval_handling                    import Interval
from   quex.blackboard                                  import E_EngineTypes, \
                                                               E_StateIndices, \
                                                               setup as Setup
from   copy      import copy
from   itertools import islice

LanguageDB = None

class SubTriggerMap(object):
    """A trigger map that 'points' into a subset of a trigger map.
       Instead of creating whole new subsets, relate to the original
       trigger map and store 'begin' and 'end' of the new map.
    """
    __slots__ = ("__trigger_map", "__begin_i", "__end_i")

    def __init__(self, TriggerMap):
        self.__trigger_map = TriggerMap
        self.__begin_i     = 0
        self.__end_i       = len(TriggerMap) - 1

    def __getitem__(self, X):
        if isinstance(X, slice):
            result = SubTriggerMap(self.__trigger_map)
            result.__begin_i = self.__begin_i + X.start
            result.__end_i   = self.__begin_i + X.stop
        else:
            return self.__trigger_map[self.__begin_i + X]

    def __len__(self):
        return self.__end_i - self.__begin_i

    def __iter__(self):
        for x in islice(self.__trigger_map, self.__begin_i, self.__end_i):
            yield x

    @property
    def middle(self):
        middle_i = int((self.__end_i - self.__begin_i) / 2) + self.__begin_i
        return self.__trigger_map[middle_i].begin

def debug(TransitionMap, Function):
    print "##--BEGIN %s" % Function
    for entry in TransitionMap:
        print "##", entry[0]
    print "##--END %s" % Function

def do(txt, TransitionMap,
       StateIndex     = None,
       EngineType     = E_EngineTypes.FORWARD,
       InitStateF     = False,
       GotoReload_Str = None,
       TheAnalyzer    = None):
    global LanguageDB
    assert isinstance(TransitionMap, list)
    assert EngineType        in E_EngineTypes
    assert isinstance(InitStateF, bool)
    assert StateIndex        is None or isinstance(StateIndex, long)
    assert GotoReload_Str    is None or isinstance(GotoReload_Str, (str, unicode))

    transition_map_tools.assert_adjacency(TransitionMap)

    # If a state has no transitions, no new input needs to be eaten => no reload.
    #
    # NOTE: The only case where the buffer reload is not required are empty states,
    #       AND states during backward input position detection!
    if len(TransitionMap) == 0: return

    LanguageDB    = Setup.language_db

    # The range of possible characters may be restricted. It must be ensured,
    # that the occurring characters only belong to the admissible range.
    solution.prune_range(TransitionMap)

    # The 'buffer-limit-code' always needs to be identified separately.
    # This helps to generate the reload procedure a little more elegantly.
    # (Backward input position detection does not reload. It only moves
    #  inside the current lexeme, which must be inside the buffer.)
    if EngineType != E_EngineTypes.BACKWARD_INPUT_POSITION:
        __separate_buffer_limit_code_transition(TransitionMap, EngineType)

    # All transition information related to intervals become proper objects of
    # class TransitionCode.
    transition_map = [ (entry[0], transition_code.do(entry[1], StateIndex, InitStateF, EngineType,
                                                     GotoReload_Str, TheAnalyzer))
                       for entry in TransitionMap ]

    # transition_map = SubTriggerMap(transition_map)
    #__________________________________________________________________________

    # (*) Determine 'outstanding' transitions and take them
    #     out of the map.
    outstanding = solution.prune_outstanding(transition_map)
    if outstanding is not None: __get_outstanding(outstanding)

    # (*) Bisection until other solution is more suitable.
    #     (This may include 'no bisectioning')
    __bisection(txt, transition_map)

    # (*) When there was an outstanding character, then the whole bisection was
    #     implemented in an 'ELSE' block which must be closed.
    if outstanding is not None: txt.append(LanguageDB.ENDIF)

def __bisection(txt, TriggerMap):
    """Creates code for state transitions from this state. This function is very
       similar to the function creating code for a 'NumberSet' condition
       (see 'interval_handling').

       Writes code that does a mapping according to 'binary search' by
       means of if-else-blocks.
    """
    global LanguageDB

    T   = len(txt)
    tip = solution.get(TriggerMap)

    # Potentially Recursive
    if   tip == solution.E_Type.BISECTION:           __get_bisection(txt, TriggerMap)
    # Direct Implementation / No more call to __bisection()
    elif tip == solution.E_Type.SWITCH_CASE:         __get_switch(txt, TriggerMap)
    elif tip == solution.E_Type.COMPARISON_SEQUENCE: __get_comparison_sequence(txt, TriggerMap)
    elif tip == solution.E_Type.TRANSITION:          __get_transition(txt, TriggerMap[0], IndentF=True)
    else:
        assert False

    # (*) Indent by four spaces (nested blocks are correctly indented)
    #     delete the last newline, to prevent additional indentation
    LanguageDB.INDENT(txt, Start=T)

def __get_outstanding(txt, TriggerMapEntry):
    txt.append(LanguageDB.IF_INPUT("==", TriggerMapEntry[0].begin))
    __get_transition(txt, TriggerMapEntry)
    txt.append(LanguageDB.ELSE)
    # Caller must provide later for 'ENDIF'

def __get_switch(txt, TriggerMap):
    """Transitions of characters that lie close to each other can be very efficiently
       be identified by a switch statement. For example:

           switch( Value ) {
           case 1: ..
           case 2: ..
           ...
           case 100: ..
           }

       Is implemented by the very few lines in assembler (i386):

           sall    $2, %eax
           movl    .L13(%eax), %eax
           jmp     *%eax

       where 'jmp *%eax' jumps immediately to the correct switch case.

       It is therefore of vital interest that those regions are **identified** and
       **not split** by a bisection. To achieve this, such regions are made a
       transition for themselves based on the character range that they cover.
    """
    global LanguageDB

    case_code_list = []
    for interval, target in TriggerMap:
        if target.drop_out_f: continue
        target_code = []
        __get_transition(target_code, (interval, target))
        case_code_list.append((range(interval.begin, interval.end), target_code))

    txt.extend(LanguageDB.SELECTION("input", case_code_list))
    txt.append("\n")
    return True

def __get_bisection(txt, TriggerMap):
    LanguageDB = Setup.language_db

    BisectionIndex = bisection.get_index(TriggerMap)

    lower  = TriggerMap[:BisectionIndex]
    higher = TriggerMap[BisectionIndex:]

    assert len(lower) != 0
    assert len(higher) != 0

    HighBegin = higher[0][0].begin
    LowBegin  = lower[0][0].begin

    def is_only_drop_out(X):
        """RETURN: True, if all intervals (actually n==1) in X only transit
                   to DROP_OUT."""
        return len(X) == 1 and X[0][1].drop_out_f

    def is_single_character(X):
        """RETURN: True, if interval of X transits on a single character."""
        return len(X) == 1 and X[0][0].size() == 1

    def get_if_statement(InverseF=False):
        if not InverseF:
            # If the size of one interval is 1, then replace the '<' by an '=='.
            if   is_single_character(lower):  return LanguageDB.IF_INPUT("==", LowBegin)
            elif is_single_character(higher): return LanguageDB.IF_INPUT("!=", HighBegin)
            else:                             return LanguageDB.IF_INPUT("<",  HighBegin)
        else:
            # If the size of one interval is 1, then replace the '>=' by an '=='.
            if   is_single_character(lower):  return LanguageDB.IF_INPUT("!=", LowBegin)
            elif is_single_character(higher): return LanguageDB.IF_INPUT("==", HighBegin)
            else:                             return LanguageDB.IF_INPUT(">=", HighBegin)

    # Note, that an '<' does involve a subtraction. A '==' only a comparison.
    # The latter is safe to be faster (or at least equally fast) on any machine.
    txt.append(0)
    if is_only_drop_out(higher):
        txt.append(get_if_statement())
        __bisection(txt, lower)
        # No 'else' case for what comes BEHIND middle => drop_out
    elif is_only_drop_out(lower):
        txt.append(get_if_statement(InverseF=True))
        __bisection(txt, higher)
        # No 'else' case for what comes BEFORE middle => drop_out
    else:
        txt.append(get_if_statement())
        __bisection(txt, lower)
        txt.append(0)
        txt.append(LanguageDB.ELSE)
        __bisection(txt, higher)

    txt.append(0)
    txt.append(LanguageDB.END_IF())

def __get_comparison_sequence(txt, TriggerMap):
    global LanguageDB

    L = len(TriggerMap)
    trigger_map = TriggerMap

    # Depending on whether the list is checked forward or backward,
    # the comparison operator and considered border may change.
    _border_cmp = "<"
    _border     = lambda interval: interval.end

    # The buffer limit code is something extreme seldom, so make sure that it is
    # tested at last, if it is there. This might require to reverse the trigger map.
    if     Setup.buffer_limit_code >= TriggerMap[0][0].begin \
       and Setup.buffer_limit_code < TriggerMap[-1][0].end:
        # Find the index of the buffer limit code in the list
        for i, candidate in enumerate(TriggerMap):
            if candidate[0].contains(Setup.buffer_limit_code): break
        if i < L / 2:
            trigger_map = copy(TriggerMap)
            trigger_map.reverse()
            _border_cmp = ">="
            _border     = lambda interval: interval.begin

    assert len(trigger_map) != 0
    L = len(trigger_map)

    LastI = L - 1
    for i, entry in enumerate(trigger_map):
        interval, target = entry

        txt.append("\n")
        txt.append(0)
        if   i == LastI:
            txt.append(LanguageDB.ELSE)
        elif interval.size() == 1:
            txt.append(LanguageDB.IF_INPUT("==", interval.begin, i==0))
        else:
            txt.append(LanguageDB.IF_INPUT(_border_cmp, _border(interval), i==0))

        if not target.drop_out_f:
            __get_transition(txt, entry, IndentF=True)

    txt.append("\n")
    txt.append(LanguageDB.END_IF(LastF=True))
    return True

def __separate_buffer_limit_code_transition(TransitionMap, EngineType):
    """This function ensures, that the buffer limit code is separated
       into a single value interval. Thus the transition map can
       transit immediate to the reload procedure.
    """
    BLC = Setup.buffer_limit_code
    for i, entry in enumerate(TransitionMap):
        interval, target_index = entry

        if   target_index == E_StateIndices.RELOAD_PROCEDURE:
            assert interval.contains_only(Setup.buffer_limit_code)
            assert EngineType != E_EngineTypes.BACKWARD_INPUT_POSITION
            # Transition 'buffer limit code --> E_StateIndices.RELOAD_PROCEDURE'
            # has been setup already.
            return

        elif target_index is not E_StateIndices.DROP_OUT:
            continue

        elif not interval.contains(Setup.buffer_limit_code):
            continue

        # Found the interval that contains the buffer limit code.
        # If the interval's size is alread 1, then there is nothing to be done
        if interval.size() == 1: return

        before_begin = interval.begin
        before_end   = BLC
        after_begin  = BLC + 1
        after_end    = interval.end

        # Replace Entry with (max.) three intervals: before, buffer limit code, after
        del TransitionMap[i]

        if after_end > after_begin:
            TransitionMap.insert(i, (Interval(after_begin, after_end), E_StateIndices.DROP_OUT))

        # "Target == E_StateIndices.RELOAD_PROCEDURE" => Buffer Limit Code
        TransitionMap.insert(i, (Interval(BLC, BLC + 1), E_StateIndices.RELOAD_PROCEDURE))

        if before_end > before_begin and before_end > 0:
            TransitionMap.insert(i, (Interval(before_begin, before_end), E_StateIndices.DROP_OUT))
        return

    # Any transition map, except for backward input position detection,
    # must have a trigger on reload.
    assert EngineType in [E_EngineTypes.BACKWARD_INPUT_POSITION, E_EngineTypes.INDENTATION_COUNTER], \
           "Engine types other than 'backward input position detection' or 'indentation counter' must contain BLC.\n" \
           "Found: %s" % repr(EngineType)
    return

def __get_transition(txt, TriggerMapEntry, IndentF=False):
    global LanguageDB

    if IndentF:
        txt.append(1)  # indent one scope

    code = TriggerMapEntry[1].code
    if type(code) == list: txt.extend(code)
    else:                  txt.append(code)

    if Setup.comment_transitions_f:
        interval = TriggerMapEntry[0]
        LanguageDB.COMMENT(txt, interval.get_utf8_string())
    else:
        txt.append("\n")
    return


text:
package com.dutproject.coffee360.model.bo;

import java.sql.SQLException;
import java.util.List;

import com.dutproject.coffee360.model.bean.Comment;
import com.dutproject.coffee360.model.bean.NewComment;
import com.dutproject.coffee360.model.bean.NewCommentVote;
import com.dutproject.coffee360.model.dao.CommentJdbcDAO;
import com.dutproject.coffee360.model.dao.UserAccountJdbcDAO;
import com.dutproject.coffee360.model.dao.provider.ICommentProvider;

public class CommentBO {
    private ICommentProvider commentProvider = new CommentJdbcDAO();

    public List<Comment> getComments(int placeId, int fromIndex, int toIndex) throws SQLException {
        return commentProvider.getComments(placeId, fromIndex, toIndex);
    }

    public Comment addComment(int placeId, int userAccountId, String message) throws SQLException {
        return commentProvider.addComment(placeId, userAccountId, message);
    }

    public Comment addComment(int accountId, NewComment comment) {
        try {
            int userAccountId = new UserAccountJdbcDAO().getUserAccountByAccountId(accountId).getUserAccountId();
            return addComment(comment.getPlaceId(), userAccountId, comment.getMessage());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Comment voteComment(NewCommentVote vote) throws SQLException {
        return commentProvider.voteComment(vote.getUserAccountId(), vote.getCommentId());
    }

}


text:
<!DOCTYPE html>

        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, minimal-ui" />

        <link href="/css/greyspots.css" type="text/css" rel="stylesheet" />

Paste here

        <gs-page>
            <gs-header>
Buttons:
</gs-header>
            <gs-body>
                <gs-table
                    id="test-table"
                    pk="id"
                    src="test.asdf3"
                    ord="id ASC"
                    limit="100000"
                    focus-on-load
                    style="width: 100%; height: 100%;"
                    copy-quote-when="strings" copy-quote-char="'" copy-escape-char="\" copy-delimiter-cell="	" copy-delimiter-record="
" copy-null-cell="NULL" copy-header="true" copy-selectors="true" copy-types="text"
                 >
                    <template for="header-record">
                        <gs-cell>id</gs-cell>
                        <gs-cell>asdf_1</gs-cell>
                        <gs-cell>asdf_2</gs-cell>
                        <gs-cell>asdf_3</gs-cell>
                    </template>
                    <template for="data-record">
                        <gs-cell header="id"><gs-text mini column="id"></gs-text></gs-cell>
                        <gs-cell header="asdf_1"><gs-text mini column="asdf_1"></gs-text></gs-cell>
                        <gs-cell header="asdf_2"><gs-text mini column="asdf_2"></gs-text></gs-cell>
                        <gs-cell header="asdf_3"><gs-text mini column="asdf_3"></gs-text></gs-cell>
                    </template>
                    <template for="insert-record">
                        <gs-cell header="id"><input column="id" /></gs-cell>
                        <gs-cell header="asdf_1"><input column="asdf_1" /></gs-cell>
                        <gs-cell header="asdf_2"><input column="asdf_2" /></gs-cell>
                        <gs-cell header="asdf_3"><input column="asdf_3" /></gs-cell>
                    </template>
                    <template for="copy">
                        <gs-cell header="id">{{! row.id }}</gs-cell>
                        <gs-cell header="asdf_1">{{! row.asdf_1 }}</gs-cell>
                        <gs-cell header="asdf_2">{{! row.asdf_2 }}</gs-cell>
                        <gs-cell header="asdf_3">{{! row.asdf_3 }}</gs-cell>
                    </template>
                </gs-table>
            </gs-body>
        </gs-page>


text:
package uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support;

import org.geotools.coverage.grid.GridCoverage2D;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.kubek2k.springockito.annotations.ReplaceWithMock;
import org.kubek2k.springockito.annotations.SpringockitoContextLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import uk.ac.ox.zoo.seeg.abraid.mp.common.domain.*;
import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.DiseaseService;
import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.ModelRunService;
import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.ValidationParameterCacheService;
import uk.ac.ox.zoo.seeg.abraid.mp.common.util.GeometryUtils;
import uk.ac.ox.zoo.seeg.abraid.mp.common.util.raster.RasterUtils;
import uk.ac.ox.zoo.seeg.abraid.mp.common.web.RasterFilePathFactory;
import uk.ac.ox.zoo.seeg.abraid.mp.testutils.AbstractSpringIntegrationTests;

import java.io.File;
import java.io.IOException;

import static com.googlecode.catchexception.CatchException.catchException;
import static com.googlecode.catchexception.CatchException.caughtException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.offset;
import static org.mockito.Mockito.*;

@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = {
    "classpath:uk/ac/ox/zoo/seeg/abraid/mp/testutils/test-context.xml",
    "classpath:uk/ac/ox/zoo/seeg/abraid/mp/common/config/beans.xml"
})
public class EnvironmentalSuitabilityHelperIntegrationTest extends AbstractSpringIntegrationTests {
    // Parameters taken from the test raster files
    private static final String LARGE_RASTER_FILENAME =
            "Common/test/uk/ac/ox/zoo/seeg/abraid/mp/common/service/workflow/support/testdata/test_raster_large_double.tif";
    private static final String ADMIN_RASTER_FILENAME =
            "Common/test/uk/ac/ox/zoo/seeg/abraid/mp/common/service/workflow/support/testdata/admin_raster_large_double.tif";
    private static final double LARGE_RASTER_COLUMNS = 720;
    private static final double LARGE_RASTER_ROWS = 240;
    private static final double LARGE_RASTER_XLLCORNER = -180;
    private static final double LARGE_RASTER_YLLCORNER = -60;
    private static final double LARGE_RASTER_CELLSIZE = 0.5;

    private DiseaseGroup diseaseGroup;

    @Autowired
    private EnvironmentalSuitabilityHelper helper;

    @Autowired
    private DiseaseService diseaseService;

    @Autowired
    private ModelRunService modelRunService;

    @Autowired
    @ReplaceWithMock
    private RasterFilePathFactory rasterFilePathFactory;

    @Autowired
    @ReplaceWithMock
    private ValidationParameterCacheService cacheService;

    @Before
    public void setUp() {
        diseaseGroup = diseaseService.getDiseaseGroupById(87);
        reset(cacheService);
        when(cacheService.getEnvironmentalSuitabilityFromCache(anyInt(), anyInt())).thenReturn(null);
    }

    @Test
    public void getLatestMeanPredictionRasterReturnsNullIfNoRelevantModelRunsForThisDiseaseGroup() throws Exception {
        // Arrange - 2 irrelevant model runs
        ModelRun modelRun1 = createAndSaveModelRun("failed", diseaseGroup.getId(), ModelRunStatus.FAILED);
        mockGetRasterFileForModelRun(modelRun1);
        ModelRun modelRun2 = createAndSaveModelRun("different disease group", 1, ModelRunStatus.COMPLETED);
        mockGetRasterFileForModelRun(modelRun2);

        // Act
        GridCoverage2D meanPredictionRaster = helper.getLatestMeanPredictionRaster(diseaseGroup);

        // Assert
        assertThat(meanPredictionRaster).isNull();
    }

    @Test
    public void findEnvironmentalSuitabilityLowerLeftCorner() throws Exception {
        findEnvironmentalSuitabilityPoint(LARGE_RASTER_XLLCORNER, LARGE_RASTER_YLLCORNER, 0.89);
        findEnvironmentalSuitabilityPrecise(LARGE_RASTER_XLLCORNER, LARGE_RASTER_YLLCORNER, 0.89);
    }

    @Test
    public void findEnvironmentalSuitabilityUpperRightCorner() throws Exception {
        double upperRightCornerX = LARGE_RASTER_XLLCORNER + (LARGE_RASTER_COLUMNS - 1) * LARGE_RASTER_CELLSIZE;
        double upperRightCornerY = LARGE_RASTER_YLLCORNER + (LARGE_RASTER_ROWS - 1) * LARGE_RASTER_CELLSIZE;
        findEnvironmentalSuitabilityPoint(upperRightCornerX, upperRightCornerY, 0.79);
        findEnvironmentalSuitabilityPrecise(upperRightCornerX, upperRightCornerY, 0.79);
    }

    @Test
    public void findEnvironmentalSuitabilityInterpolated() throws Exception {
        double lowerLeftCornerSlightlyShiftedX = LARGE_RASTER_XLLCORNER + (LARGE_RASTER_CELLSIZE * 0.5);
        double lowerLeftCornerSlightlyShiftedY = LARGE_RASTER_YLLCORNER + (LARGE_RASTER_CELLSIZE * 0.5);
        findEnvironmentalSuitabilityPoint(lowerLeftCornerSlightlyShiftedX, lowerLeftCornerSlightlyShiftedY, 0.89);
        findEnvironmentalSuitabilityPrecise(lowerLeftCornerSlightlyShiftedX, lowerLeftCornerSlightlyShiftedY, 0.89);
    }

    @Test
    public void findEnvironmentalSuitabilityOutOfRasterRange() throws Exception {
        double oneCellBeyondUpperRightCornerX = LARGE_RASTER_XLLCORNER + LARGE_RASTER_COLUMNS * LARGE_RASTER_CELLSIZE;
        double oneCellBeyondUpperRightCornerY = LARGE_RASTER_YLLCORNER + LARGE_RASTER_ROWS * LARGE_RASTER_CELLSIZE;
        findEnvironmentalSuitabilityPoint(oneCellBeyondUpperRightCornerX, oneCellBeyondUpperRightCornerY, null);
        findEnvironmentalSuitabilityPrecise(oneCellBeyondUpperRightCornerX, oneCellBeyondUpperRightCornerY, null);
    }

    @Test
    public void findEnvironmentalSuitabilityNoDataValueWithinRasterRange() throws Exception {
        // The NODATA value in the raster is in column 6 row 12 (from the top left)
        double noDataValueX = LARGE_RASTER_XLLCORNER + 5 * LARGE_RASTER_CELLSIZE;
        double noDataValueY = LARGE_RASTER_YLLCORNER + (LARGE_RASTER_ROWS - 12) * LARGE_RASTER_CELLSIZE;
        findEnvironmentalSuitabilityPoint(noDataValueX, noDataValueY, null);
        findEnvironmentalSuitabilityPrecise(noDataValueX, noDataValueY, null);
    }

    @Test
    public void findEnvironmentalSuitabilityNoDataInShape() throws Exception {
        // Falls back to precise
        double upperRightCornerX = LARGE_RASTER_XLLCORNER + (LARGE_RASTER_COLUMNS - 1) * LARGE_RASTER_CELLSIZE;
        double upperRightCornerY = LARGE_RASTER_YLLCORNER + (LARGE_RASTER_ROWS - 1) * LARGE_RASTER_CELLSIZE;
        findEnvironmentalSuitabilityShape(upperRightCornerX, upperRightCornerY, 987, LocationPrecision.COUNTRY, 0.79);
    }

    @Test
    public void findEnvironmentalSuitabilityShapeHalfNoData() throws Exception {
        findEnvironmentalSuitabilityShape(0, 0, 654, LocationPrecision.ADMIN1, 0.504699);
    }

    @Test
    public void findEnvironmentalSuitabilityShapeFullPopulated() throws Exception {
        findEnvironmentalSuitabilityShape(0, 0, 321, LocationPrecision.ADMIN2, 0.491874);
    }

    @Test
    public void findEnvironmentalSuitabilityUsesCachedValue() throws Exception {
        // Arrange
        DiseaseOccurrence occurrence = createOccurrence(1, 1, 1, LocationPrecision.PRECISE);
        ModelRun modelRun = createAndSaveModelRun("test name", diseaseGroup.getId(), ModelRunStatus.COMPLETED);
        mockGetRasterFileForModelRun(modelRun);
        GridCoverage2D suitabilityRaster = null;
        GridCoverage2D[] adminRasters = null;
        try {
            suitabilityRaster = helper.getLatestMeanPredictionRaster(diseaseGroup);
            adminRasters = helper.getSingleAdminRaster(LocationPrecision.PRECISE);

            when(cacheService.getEnvironmentalSuitabilityFromCache(occurrence.getDiseaseGroup().getId(), occurrence.getLocation().getId())).thenReturn(12345d);

            // Act
            Double suitability = helper.findEnvironmentalSuitability(occurrence, suitabilityRaster, adminRasters);

            // Assert
            assertThat(suitability).isEqualTo(12345d);
        } finally {
            RasterUtils.disposeRaster(suitabilityRaster);
            RasterUtils.disposeRasters(adminRasters);
        }
    }

    @Test
    public void createCroppedEnvironmentalSuitabilityRasterCropsCorrectArea() throws Exception {
        // Arrange
        File suitabilityRaster = new File(LARGE_RASTER_FILENAME);
        File adminRaster = new File(ADMIN_RASTER_FILENAME);
        int gaul = 321;

        // Act
        File cropped = helper.createCroppedEnvironmentalSuitabilityRaster(gaul, adminRaster, suitabilityRaster);

        // Assert
        File adminRasterCroppedBy321 = new File("Common/test/uk/ac/ox/zoo/seeg/abraid/mp/common/service/workflow/support/testdata/test_raster_large_double_cropped_by_321.tif");
        assertThat(cropped).hasContentEqualTo(adminRasterCroppedBy321);
        assertThat(cropped.delete()).isTrue();
    }

    @Test
    public void createCroppedEnvironmentalSuitabilityRasterCropsCorrectAreaWithWaterBody() throws Exception {
        // Arrange
        File suitabilityRaster = new File(LARGE_RASTER_FILENAME);
        File adminRaster = new File(ADMIN_RASTER_FILENAME);
        int gaul = 654;

        // Act
        File cropped = helper.createCroppedEnvironmentalSuitabilityRaster(gaul, adminRaster, suitabilityRaster);

        // Assert
        File adminRasterCroppedBy654 = new File("Common/test/uk/ac/ox/zoo/seeg/abraid/mp/common/service/workflow/support/testdata/test_raster_large_double_cropped_by_654.tif");
        assertThat(cropped).hasContentEqualTo(adminRasterCroppedBy654);
        assertThat(cropped.delete()).isTrue();
    }

    @Test
    public void createCroppedEnvironmentalSuitabilityRasterWhenNoMatchingPixels() throws Exception {
        // Arrange
        File suitabilityRaster = new File(LARGE_RASTER_FILENAME);
        File adminRaster = new File(ADMIN_RASTER_FILENAME);
        int gaul = 123;

        // Act
        catchException(helper).createCroppedEnvironmentalSuitabilityRaster(gaul, adminRaster, suitabilityRaster);

        // Assert
        assertThat(caughtException()).isInstanceOf(IOException.class);
        assertThat(caughtException().getMessage()).isEqualTo("The specified country does not appear to cover any raster pixels.");
    }

    private ModelRun createAndSaveModelRun(String name, int diseaseGroupId, ModelRunStatus status) {
        ModelRun modelRun = new ModelRun(name, diseaseService.getDiseaseGroupById(diseaseGroupId), "host", DateTime.now(), DateTime.now(), DateTime.now());
        modelRun.setStatus(status);
        modelRun.setResponseDate(DateTime.now());
        modelRunService.saveModelRun(modelRun);
        return modelRun;
    }

    private void mockGetRasterFileForModelRun(ModelRun modelRun) {
        when(rasterFilePathFactory.getFullMeanPredictionRasterFile(same(modelRun)))
                .thenReturn(new File(LARGE_RASTER_FILENAME));
    }

    private void mockGetAdminRasterFileForLevel(int level) {
        when(rasterFilePathFactory.getAdminRaster(level)).thenReturn(new File(ADMIN_RASTER_FILENAME));
    }

    private void findEnvironmentalSuitabilityPrecise(double x, double y,
                                                     Double expectedEnvironmentalSuitability) throws Exception {
        // Arrange
        DiseaseOccurrence occurrence = createOccurrence(x, y, 1, LocationPrecision.PRECISE);
        ModelRun modelRun = createAndSaveModelRun("test name", diseaseGroup.getId(), ModelRunStatus.COMPLETED);
        mockGetRasterFileForModelRun(modelRun);
        GridCoverage2D suitabilityRaster = null;
        GridCoverage2D[] adminRasters = null;
        try {
            suitabilityRaster = helper.getLatestMeanPredictionRaster(diseaseGroup);
            adminRasters = helper.getSingleAdminRaster(LocationPrecision.PRECISE);

            // Act
            Double suitability = helper.findEnvironmentalSuitability(occurrence, suitabilityRaster, adminRasters);

            // Assert
            assertThat(suitabilityRaster).isNotNull();
            assertThat(adminRasters).isNotNull();
            assertThat(adminRasters[0]).isNull();
            assertThat(adminRasters[1]).isNull();
            assertThat(adminRasters[2]).isNull();
            if (expectedEnvironmentalSuitability != null) {
                assertThat(suitability).isEqualTo(expectedEnvironmentalSuitability, offset(0.0000005));
                verify(cacheService).saveEnvironmentalSuitabilityCacheEntry(occurrence.getDiseaseGroup().getId(), occurrence.getLocation().getId(), suitability);
            } else {
                assertThat(suitability).isNull();
            }
        } finally {
            RasterUtils.disposeRaster(suitabilityRaster);
            RasterUtils.disposeRasters(adminRasters);
        }
    }

    private void findEnvironmentalSuitabilityPoint(double x, double y,
                                                     Double expectedEnvironmentalSuitability) throws Exception {
        // Arrange
        ModelRun modelRun = createAndSaveModelRun("test name 1", diseaseGroup.getId(), ModelRunStatus.COMPLETED);
        mockGetRasterFileForModelRun(modelRun);
        File suitabilityRaster = rasterFilePathFactory.getFullMeanPredictionRasterFile(modelRun);
        double offsetForRounding = 0.00005;

        // Act
        Double suitability = helper.findPointEnvironmentalSuitability(suitabilityRaster, GeometryUtils.createPoint(x + offsetForRounding,  y + offsetForRounding));

        // Assert
        if (expectedEnvironmentalSuitability != null) {
            assertThat(suitability).isEqualTo(expectedEnvironmentalSuitability, offset(0.0000005));
        } else {
            assertThat(suitability).isNull();
        }
    }

    private void findEnvironmentalSuitabilityShape(double x, double y, int gaul, LocationPrecision precision,
                                                     Double expectedEnvironmentalSuitability) throws Exception {
        // Arrange
        DiseaseOccurrence occurrence = createOccurrence(x, y, gaul, precision);
        ModelRun modelRun = createAndSaveModelRun("test name", diseaseGroup.getId(), ModelRunStatus.COMPLETED);
        mockGetRasterFileForModelRun(modelRun);
        mockGetAdminRasterFileForLevel(precision.getModelValue());
        mockGetRasterFileForModelRun(modelRun);
        GridCoverage2D suitabilityRaster = null;
        GridCoverage2D[] adminRasters = null;
        try {
            suitabilityRaster = helper.getLatestMeanPredictionRaster(diseaseGroup);
            adminRasters = helper.getSingleAdminRaster(precision);

            // Act
            Double suitability = helper.findEnvironmentalSuitability(occurrence, suitabilityRaster, adminRasters);

            // Assert
            assertThat(suitabilityRaster).isNotNull();
            assertThat(adminRasters).isNotNull();
            assertThat(adminRasters[precision.getModelValue()]).isNotNull();
            if (expectedEnvironmentalSuitability != null) {
                assertThat(suitability).isEqualTo(expectedEnvironmentalSuitability, offset(0.0000005));
                verify(cacheService).saveEnvironmentalSuitabilityCacheEntry(occurrence.getDiseaseGroup().getId(), occurrence.getLocation().getId(), suitability);
            } else {
                assertThat(suitability).isNull();
            }
        } finally {
            RasterUtils.disposeRaster(suitabilityRaster);
            RasterUtils.disposeRasters(adminRasters);
        }
    }

    private DiseaseOccurrence createOccurrence(double x, double y, int gaul, LocationPrecision precision) {
        double offsetForRounding = 0.00005;
        DiseaseOccurrence occurrence = new DiseaseOccurrence();
        Location location = mock(Location.class);
        when(location.getGeom()).thenReturn(GeometryUtils.createPoint(x + offsetForRounding,  y + offsetForRounding));
        when(location.getPrecision()).thenReturn(precision);
        if (precision == LocationPrecision.COUNTRY) {
            when(location.getCountryGaulCode()).thenReturn(gaul);
        } else {
            when(location.getAdminUnitQCGaulCode()).thenReturn(gaul);
        }
        occurrence.setLocation(location);
        occurrence.setDiseaseGroup(diseaseGroup);
        return occurrence;
    }
}


text:
namespace Tranquire.Selenium.Questions
{
    /// <summary>
    /// A question returning the page title
    /// </summary>
    public class PageTitle : QuestionBase<WebBrowser, string>
    {
        /// <summary>
        /// Returns the page title
        /// </summary>
        /// <param name="actor"></param>
        /// <param name="ability"></param>
        /// <returns></returns>
        protected override string Answer(IActor actor, WebBrowser ability)
        {
            return ability.Driver.Title;
        }

        /// <summary>
        /// Gets the action's name
        /// </summary>
        public override string Name => "Page title";
    }
}


text:
<?php
namespace Concrete\Core\Search\Column;

use Loader;

class AttributeKeyColumn extends Column
{
    protected $attributeKey = false;

    public function getAttributeKey()
    {
        return $this->attributeKey;
    }

    public function __construct($attributeKey, $isSortable = true, $defaultSort = 'asc')
    {
        $this->attributeKey = $attributeKey;
        parent::__construct('ak_' . $attributeKey->getAttributeKeyHandle(), $attributeKey->getAttributeKeyDisplayName(), false, $isSortable, $defaultSort);
    }

    public function getColumnValue($obj)
    {
        if (is_object($this->attributeKey)) {
            $vo = $obj->getAttributeValueObject($this->attributeKey);
            if (is_object($vo)) {
                return $vo->getValue('display');
            }
        }
    }
}


text:
001
004
005    package com.rattat.micro.game.frog.board.elements;
006
007    import com.rattat.micro.game.frog.board.elements.Home;
008
009    /**
010     * HomeListener interface should be implemented by objects wishing to be
011     * notified of home events. e.g. player lands on cell, insect gets eaten etc.
012     *
013     * @author william@rattat.com
014     */
015    public interface HomeListener {
016
017        /**
018         * Called when a HomeEvent happens
019         *
020         * @param int event
021         * @param Home home
022         */
023        public void homeEvent(int event, Home home);
024    }


text:
package SH::Code::Template;
use Mojo::Base -base;
use Mojo::File 'path';
use Clone 'clone';
use open ':encoding(UTF-8)';
use utf8;
use Encode;
use Carp::Always;
use Data::Printer;

=encoding utf8

=head1 NAME

SH::Code::Template - parent of the templates.

=head1 SYNOPSIS

 package SH::Code::Template::ScriptX;
 use Mojo::Base 'SH::Code::Template';
 sub name {'testing'};

=head1 DESCRIPTION

Basis for templates. A template should generate a template for code file(script, module)
and a test file. And sometimes extra like config file example.

The template should make it easy to start coding.

=head1 ATTRIBUTES

=head2 dryrun

Do not make files but print instead.

=head2 force

Over write existing files. Nice when developing new templates.

=cut

has 'dryrun';
has 'force';

=head1 METHODS

=head2 name

Friendly name of the module. Used by the template parameter.
This must be replaced in child object.
=cut

sub name {
    my $self = shift;
    die "Missing name for module ". ref $self;
}

=head2 help_text

Text which is printed with the helptemplate option.
This must be replaced in child object.

=cut

sub help_text {
    my $self = shift;
    die "Missing help_text for module ". ref $self;
}

=head2 generate

Called when script will generate files.
This must be replaced in child object.

=cut

sub generate {
    my $self = shift;
    die "Missing generate method for module ". ref $self;
}

=head2  generate_file

Generate wished file based on input. Fi le must not exists else an error will be shown.

input is a hash ref with following keys.

=over 2

=item path - Relative and must exists.

=item filename - Filename

=item ts - template as string. Template protocol Mojo::Template

=item parameters - all parameters for the template

=back

=cut

sub generate_file {
    my $self = shift;
    my $input = shift;
    die "Missing path" if ! exists $input->{path};
    die "Missing filename" if ! exists $input->{filename};
    die "Missing ts" if ! exists $input->{ts} || ! $input->{ts};
    my $mt = Mojo::Template->new(vars=>1);
    my $out = $mt->render( $input->{ts}, $input->{parameters} );
    if ($out =~/line \d+/) {
        warn $input->{ts};
        die $out;
    }

    my $pa =path( $input->{path} );
    if (! -d "$pa") {
	    if ($self->force) {
	    	$pa->make_path;
	    } else {
	        die "Path $pa must exists from current path or use options --force. Bail out!";
	    }
	}
    my $fi = $pa->child($input->{filename});
    if (! $self->force && -e "$fi") {
        die "$fi exists! Bail out!";
    }
    if ($self->dryrun) {
        say $out;
    } else {
        $fi->spurt(Encode::encode('UTF-8',$out)); # spurt is hard with utf8
        # $fi->chmod(0755); does not work on Mojolicious 7.70
        chmod(0755, "$fi");
    }

}

=head2 required_variables

This methods should return a 2-parameter array of array. [['param','desc'],[p2,'d2']]
This must be set in child object.

=cut

sub required_variables {
    my $self = shift;
    die "Missing required_variables in ". ref $self;
}

=head2 optional_variables

This methods should return 2 parameter array of array [['param','desc'],[p2,'d2']]

=cut

sub optional_variables {
    my $self = shift;
    return [];
}

=head2 get_missing_param

Look for missing parameters. Ask user if found missing  required parameter.

=cut

sub get_missing_param {
    my $self = shift;
    my $params = clone shift;
    for my $p (@{$self->required_variables}) {
        if (!exists $params->{$p->[0]}) {
            say $p->[0] .': '. $p->[1];
            print "$p->[0]: ";
            $params->{$p->[0]} = <STDIN>;
            chomp($params->{$p->[0]});
        }
    }
    return  $params;
}

=head2 pad_optional_param

Set value to undef if value is not defined.

=cut

sub pad_optional_param {
    my $self = shift;
    my $params = clone shift;
    p $self;
    return  $params if ! @{$self->optional_variables};
    for my $p (@{$self->optional_variables}) {
        if (!exists $params->{$p->[0]}) {
            say $p->[0] .': '. $p->[1];
            print "$p->[0]: ";
            $params->{$p->[0]} = undef;
        }
    }
    return  $params;
}

=head2 xdata_section

Call Mojo::Loader::data_section
Check input output

=cut

sub xdata_section {
    my $self = shift;
    my $return = Mojo::Loader::data_section(@_);
    die "Cant find datasection for ".join(', ', @_) if ! $return;
    return $return;
}

=head1 AUTHOR

Slegga

=cut

1;


text: Collection of common code files that for whatever reason do not belong in a NuGet package.