text:
package mplinux

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"

	mp "github.com/mackerelio/go-mackerel-plugin-helper"
	"github.com/urfave/cli"
)

const (
	pathVmstat = "/proc/vmstat"
	pathStat   = "/proc/stat"
	pathSysfs  = "/sys"
)

// metric value structure
// note: all metrics are add dynamic at collect*().
var graphdef = map[string]mp.Graphs{}

// LinuxPlugin mackerel plugin for linux
type LinuxPlugin struct {
	Tempfile string
	Typemap  map[string]bool
}

// GraphDefinition interface for mackerelplugin
func (c LinuxPlugin) GraphDefinition() map[string]mp.Graphs {
	var err error

	p := make(map[string]interface{})

	if c.Typemap["all"] || c.Typemap["swap"] {
		err = collectProcVmstat(pathVmstat, &p)
		if err != nil {
			return nil
		}
	}

	if c.Typemap["all"] || c.Typemap["netstat"] {
		err = collectNetworkStat(&p)
		if err != nil {
			return nil
		}
	}

	if c.Typemap["all"] || c.Typemap["diskstats"] {
		err = collectDiskStats(pathSysfs, &p)
		if err != nil {
			return nil
		}
	}

	if c.Typemap["all"] || c.Typemap["proc_stat"] {
		err = collectProcStat(pathStat, &p)
		if err != nil {
			return nil
		}
	}

	if c.Typemap["all"] || c.Typemap["users"] {
		err = collectWho(&p)
		if err != nil {
			return nil
		}
	}

	return graphdef
}

// main function
func doMain(c *cli.Context) error {
	var linux LinuxPlugin

	typemap := map[string]bool{}
	types := c.StringSlice("type")
	// If no `type` is specified, fetch all metrics
	if len(types) == 0 {
		typemap["all"] = true
	} else {
		for _, t := range types {
			typemap[t] = true
		}
	}
	linux.Typemap = typemap
	helper := mp.NewMackerelPlugin(linux)
	helper.Tempfile = c.String("tempfile")

	helper.Run()
	return nil
}

// FetchMetrics interface for mackerelplugin
func (c LinuxPlugin) FetchMetrics() (map[string]interface{}, error) {
	var err error

	p := make(map[string]interface{})

	if c.Typemap["all"] || c.Typemap["swap"] {
		err = collectProcVmstat(pathVmstat, &p)
		if err != nil {
			return nil, err
		}
	}

	if c.Typemap["all"] || c.Typemap["netstat"] {
		err = collectNetworkStat(&p)
		if err != nil {
			return nil, err
		}
	}

	if c.Typemap["all"] || c.Typemap["diskstats"] {
		err = collectDiskStats(pathSysfs, &p)
		if err != nil {
			return nil, err
		}
	}

	if c.Typemap["all"] || c.Typemap["proc_stat"] {
		err = collectProcStat(pathStat, &p)
		if err != nil {
			return nil, err
		}
	}

	if c.Typemap["all"] || c.Typemap["users"] {
		err = collectWho(&p)
		if err != nil {
			return nil, err
		}
	}

	return p, nil
}

// collect who
func collectWho(p *map[string]interface{}) error {
	var err error
	var data string

	graphdef["linux.users"] = mp.Graphs{
		Label: "Linux Users",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "users", Label: "Users", Diff: false},
		},
	}

	data, err = getWho()
	if err != nil {
		return err
	}
	err = parseWho(data, p)
	if err != nil {
		return err
	}

	return nil
}

// parsing metrics from /proc/stat
func parseWho(str string, p *map[string]interface{}) error {
	str = strings.TrimSpace(str)
	if str == "" {
		(*p)["users"] = 0
		return nil
	}
	line := strings.Split(str, "\n")
	(*p)["users"] = float64(len(line))

	return nil
}

// Getting who
func getWho() (string, error) {
	cmd := exec.Command("who")
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		return "", err
	}
	return out.String(), nil
}

// collect /proc/stat
func collectProcStat(path string, p *map[string]interface{}) error {
	graphdef["linux.interrupts"] = mp.Graphs{
		Label: "Linux Interrupts",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "interrupts", Label: "Interrupts", Diff: true},
		},
	}
	graphdef["linux.context_switches"] = mp.Graphs{
		Label: "Linux Context Switches",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "context_switches", Label: "Context Switches", Diff: true},
		},
	}
	graphdef["linux.forks"] = mp.Graphs{
		Label: "Linux Forks",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "forks", Label: "Forks", Diff: true},
		},
	}

	file, err := os.Open(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return parseProcStat(file, p)
}

// parsing metrics from /proc/stat
func parseProcStat(r io.Reader, p *map[string]interface{}) error {
	scanner := bufio.NewScanner(r)

	for scanner.Scan() {
		line := scanner.Text()
		record := strings.Fields(line)
		if len(record) < 2 {
			continue
		}
		name := record[0]
		value, errParse := atof(record[1])
		if errParse != nil {
			return errParse
		}

		if name == "intr" {
			(*p)["interrupts"] = value
		} else if name == "ctxt" {
			(*p)["context_switches"] = value
		} else if name == "processes" {
			(*p)["forks"] = value
		}
	}

	return nil
}

// collect /sys/block/<device>/stat
// See also. http://man7.org/linux/man-pages/man5/sysfs.5.html
func collectDiskStats(path string, p *map[string]interface{}) error {
	var elapsedData []mp.Metrics
	var rwtimeData []mp.Metrics

	sysBlockDir := filepath.Join(path, "block")

	devices, err := ioutil.ReadDir(sysBlockDir)
	if err != nil {
		return err
	}

	for _, d := range devices {
		if d.Mode()&os.ModeSymlink != os.ModeSymlink {
			continue
		}

		name := d.Name()

		// /sys/block/<device> is a symbolic link for block device
		realPath, err := filepath.EvalSymlinks(filepath.Join(sysBlockDir, name))
		if err != nil {
			return err
		}

		// exclude virtual device
		if strings.Index(realPath, "/devices/virtual/") != -1 {
			continue
		}

		// exclude removable device
		content, err := ioutil.ReadFile(filepath.Join(realPath, "removable"))
		if err != nil {
			return err
		}
		if len(content) > 0 && string(content[0]) == "1" {
			continue
		}

		content, err = ioutil.ReadFile(filepath.Join(realPath, "stat"))
		if err != nil {
			return err
		}

		err = parseDiskStat(name, string(content), p)
		if err != nil {
			return err
		}

		elapsedData = append(elapsedData, mp.Metrics{Name: fmt.Sprintf("iotime_%s", name), Label: fmt.Sprintf("%s IO Time", name), Diff: true})
		elapsedData = append(elapsedData, mp.Metrics{Name: fmt.Sprintf("iotime_weighted_%s", name), Label: fmt.Sprintf("%s IO Time Weighted", name), Diff: true})

		rwtimeData = append(rwtimeData, mp.Metrics{Name: fmt.Sprintf("tsreading_%s", name), Label: fmt.Sprintf("%s Read", name), Diff: true})
		rwtimeData = append(rwtimeData, mp.Metrics{Name: fmt.Sprintf("tswriting_%s", name), Label: fmt.Sprintf("%s Write", name), Diff: true})
	}

	graphdef["linux.disk.elapsed"] = mp.Graphs{
		Label:   "Disk Elapsed IO Time",
		Unit:    "integer",
		Metrics: elapsedData,
	}

	graphdef["linux.disk.rwtime"] = mp.Graphs{
		Label:   "Disk Read/Write Time",
		Unit:    "integer",
		Metrics: rwtimeData,
	}

	return nil
}

func parseDiskStat(name, stat string, p *map[string]interface{}) error {
	fields := strings.Fields(stat)
	if len(fields) != 11 {
		return nil
	}

	// See also. https://www.kernel.org/doc/Documentation/block/stat.txt
	(*p)[fmt.Sprintf("iotime_%s", name)], _ = atof(fields[9])           // io_ticks
	(*p)[fmt.Sprintf("iotime_weighted_%s", name)], _ = atof(fields[10]) // time_in_queue
	(*p)[fmt.Sprintf("tsreading_%s", name)], _ = atof(fields[3])        // read ticks
	(*p)[fmt.Sprintf("tswriting_%s", name)], _ = atof(fields[7])        // write ticks

	return nil
}

// collect ss
func collectNetworkStat(p *map[string]interface{}) error {
	graphdef["linux.ss"] = mp.Graphs{
		Label: "Linux Network Connection States",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "ESTAB", Label: "Established", Diff: false, Stacked: true},
			{Name: "SYN-SENT", Label: "Syn Sent", Diff: false, Stacked: true},
			{Name: "SYN-RECV", Label: "Syn Received", Diff: false, Stacked: true},
			{Name: "FIN-WAIT-1", Label: "Fin Wait 1", Diff: false, Stacked: true},
			{Name: "FIN-WAIT-2", Label: "Fin Wait 2", Diff: false, Stacked: true},
			{Name: "TIME-WAIT", Label: "Time Wait", Diff: false, Stacked: true},
			{Name: "UNCONN", Label: "Close", Diff: false, Stacked: true},
			{Name: "CLOSE-WAIT", Label: "Close Wait", Diff: false, Stacked: true},
			{Name: "LAST-ACK", Label: "Last Ack", Diff: false, Stacked: true},
			{Name: "LISTEN", Label: "Listen", Diff: false, Stacked: true},
			{Name: "CLOSING", Label: "Closing", Diff: false, Stacked: true},
			{Name: "UNKNOWN", Label: "Unknown", Diff: false, Stacked: true},
		},
	}

	cmd := exec.Command("ss", "-na")
	out, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	if err := parseSs(out, p); err != nil {
		return err
	}
	return cmd.Wait()
}

// parsing metrics from ss
func parseSs(r io.Reader, p *map[string]interface{}) error {
	status := 0
	first := true
	scanner := bufio.NewScanner(r)

	for scanner.Scan() {
		line := scanner.Text()
		record := strings.Fields(line)
		if len(record) < 5 {
			continue
		}
		if first {
			first = false
			if record[0] == "State" {
				// for RHEL6
				status = 0
			} else if record[1] == "State" {
				// for RHEL7
				status = 1
			}
		}
		v, _ := (*p)[record[status]].(float64)
		(*p)[record[status]] = v + 1
	}

	return nil
}

// collect /proc/vmstat
func collectProcVmstat(path string, p *map[string]interface{}) error {
	graphdef["linux.swap"] = mp.Graphs{
		Label: "Linux Swap Usage",
		Unit:  "integer",
		Metrics: []mp.Metrics{
			{Name: "pswpin", Label: "Swap In", Diff: true},
			{Name: "pswpout", Label: "Swap Out", Diff: true},
		},
	}

	file, err := os.Open(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return parseProcVmstat(file, p)
}

// parsing metrics from /proc/vmstat
func parseProcVmstat(r io.Reader, p *map[string]interface{}) error {
	scanner := bufio.NewScanner(r)

	for scanner.Scan() {
		line := scanner.Text()
		record := strings.Fields(line)
		if len(record) != 2 {
			continue
		}
		var errParse error
		(*p)[record[0]], errParse = atof(record[1])
		if errParse != nil {
			return errParse
		}
	}

	return nil
}

// atof
func atof(str string) (float64, error) {
	return strconv.ParseFloat(strings.Trim(str, " "), 64)
}

// Do the plugin
func Do() {
	app := cli.NewApp()
	app.Name = "mackerel-plugin-linux"
	app.Version = version
	app.Usage = "Get metrics from Linux."
	app.Author = "Yuichiro Saito"
	app.Email = "saito@heartbeats.jp"
	app.Flags = flags
	app.Action = doMain

	app.Run(os.Args)
}


text:
from app.model import Database

class Support:
    def __init__(self):
        self.db = Database() # Just for testing
        self.cur = self.db.getcursor()

    def get_cases(self):
            self.cur.execute("SELECT * FROM `cases_table`")

            data = self.cur.fetchall()

            self.db.conn.close()

            return data

    def add_case(self,customerid,name,product,info):
        import random
        caseid = int(str(random.randint(0,99)) + str(random.randint(0,99)))
        self.cur.execute(""" INSERT INTO `cases_table`(caseid,customerid,name,product,info) VALUES('{}','{}','{}','{}','{}')""".format(caseid,customerid,name,product,info))
        self.db.conn.commit()

    def edit_case(self,caseid,customerid,name,product,info):
        self.cur.execute(""" UPDATE `cases_table` SET customerid='{}',name='{}',product='{}',info='{}' WHERE caseid='{}'""".format(customerid,name,product,info,caseid))
        self.db.conn.commit()

    def delete_case(self,caseid):
        self.cur.execute(""" DELETE FROM `cases_table` WHERE caseid='{}' """.format(caseid))
        self.db.conn.commit()

    def get_case(self,caseid):
        self.cur.execute(""" SELECT * FROM `cases_table` WHERE caseid='{}' """.format(caseid))

        data = self.cur.fetchall()

        return data[0]

redpajama_set_name: RedPajamaGithub


text:
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")

include("shared.lua")

function ENT:Initialize()
    self:SetModel("models/props_lab/clipboard.mdl")
    DarkRP.ValidatedPhysicsInit(self, SOLID_VPHYSICS)
    self:SetMoveType(MOVETYPE_VPHYSICS)
    self:SetSolid(SOLID_VPHYSICS)
    self:SetUseType(SIMPLE_USE)

    self.nodupe = true

    local phys = self:GetPhysicsObject()

    if phys:IsValid() then
        phys:Wake()
    end

    hook.Add("PlayerDisconnected", self, self.onPlayerDisconnected)
end

function ENT:Use(activator, caller)
    local canUse, reason = hook.Call("canDarkRPUse", nil, activator, self, caller)
    if canUse == false then
        if reason then DarkRP.notify(activator, 1, 4, reason) end
        return
    end

    local owner = self:Getowning_ent()
    local recipient = self:Getrecipient()
    local amount = self:Getamount() or 0

    if (IsValid(activator) and IsValid(recipient)) and activator == recipient then
        owner = (IsValid(owner) and owner:Nick()) or DarkRP.getPhrase("disconnected_player")
        DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("found_cheque", DarkRP.formatMoney(amount), "", owner))
        activator:addMoney(amount)
        hook.Call("playerPickedUpCheque", nil, activator, recipient, amount or 0, true, self)
        self:Remove()
    elseif (IsValid(owner) and IsValid(recipient)) and owner ~= activator then
        DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("cheque_details", recipient:Nick()))
        hook.Call("playerPickedUpCheque", nil, activator, recipient, amount or 0, false, self)
    elseif IsValid(owner) and owner == activator then
        DarkRP.notify(activator, 0, 4, DarkRP.getPhrase("cheque_torn"))
        owner:addMoney(self:Getamount()) -- return the money on the cheque to the owner.
        hook.Call("playerToreUpCheque", nil, activator, recipient, amount, self)
        self:Remove()
    elseif not IsValid(recipient) then self:Remove()
    end
end

function ENT:StartTouch(ent)
    -- the .USED var is also used in other mods for the same purpose
    if ent:GetClass() ~= "darkrp_cheque" or self.USED or ent.USED or self.hasMerged or ent.hasMerged then return end
    if ent:Getowning_ent() ~= self:Getowning_ent() then return end
    if ent:Getrecipient() ~= self:Getrecipient() then return end

    -- Both hasMerged and USED are used by third party mods. Keep both in.
    ent.USED = true
    ent.hasMerged = true

    ent:Remove()
    self:Setamount(self:Getamount() + ent:Getamount())
end

function ENT:OnTakeDamage(dmg)
    self:TakePhysicsDamage(dmg)

    local typ = dmg:GetDamageType()
    if bit.band(typ, bit.bor(DMG_FALL, DMG_VEHICLE, DMG_DROWN, DMG_RADIATION, DMG_PHYSGUN)) > 0 then return end

    self.USED = true
    self.hasMerged = true
    self:Remove()
end

function ENT:onPlayerDisconnected(ply)
    if self:Getowning_ent() == ply or self:Getrecipient() == ply then
        self:Remove()
    end
end

DarkRP.hookStub{
    name = "playerPickedUpCheque",
    description = "Called when a player picks up a cheque.",
    parameters = {
        {
            name = "player",
            description = "The player who attempted to pick up the cheque.",
            type = "Player"
        },
        {
            name = "player",
            description = "The player who the cheque was written to.",
            type = "Player"
        },
        {
            name = "amount",
            description = "The amount of money the cheque has.",
            type = "number"
        },
        {
            name = "success",
            description = "Whether the player was allowed to cash the cheque.",
            type = "bool"
        },
        {
            name = "entity",
            description = "The entity of the cheque.",
            type = "Entity"
        }
    },
    returns = {
    },
    realm = "Server"
}

DarkRP.hookStub{
    name = "playerToreUpCheque",
    description = "Called when a player tears up a cheque.",
    parameters = {
        {
            name = "player",
            description = "The player who tore up the cheque.",
            type = "Player"
        },
        {
            name = "player",
            description = "The player who the cheque was written to.",
            type = "Player"
        },
        {
            name = "amount",
            description = "The amount of money the cheque has.",
            type = "number"
        },
        {
            name = "entity",
            description = "The entity of the cheque.",
            type = "Entity"
        }
    },
    returns = {
    },
    realm = "Server"
}


text:
package org.apache.sis.filter;

import java.util.List;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import org.apache.sis.xml.NilReason;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.internal.filter.Node;

// Branch-dependent imports
import org.apache.sis.internal.geoapi.filter.ComparisonOperatorName;

/**
 * Base class for expressions, comparators or filters performing operations on one expressions.
 * The nature of the operation depends on the subclass.
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.1
 *
 * @param  <R>  the type of resources (e.g. {@code Feature}) used as inputs.
 * @param  <V>  the type of value computed by the expression.
 *
 * @since 1.1
 * @module
 */
class UnaryFunction<R,V> extends Node {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 2020526901451551162L;

    /**
     * The expression to be used by this operator.
     *
     * @see #getExpression()
     */
    protected final Expression<? super R, ? extends V> expression;

    /**
     * Creates a new unary operator.
     */
    UnaryFunction(final Expression<? super R, ? extends V> expression) {
        ArgumentChecks.ensureNonNull("expression", expression);
        this.expression = expression;
    }

    /**
     * Returns the expression used as parameter by this function.
     * Defined for {@link Expression#getParameters()} implementations.
     */
    public final List<Expression<? super R, ?>> getParameters() {
        return getExpressions();
    }

    /**
     * Returns the expression used as parameter by this filter.
     * Defined for {@link Filter#getExpressions()} implementations.
     *
     * @return a list of size 1 containing the singleton expression.
     */
    public final List<Expression<? super R, ?>> getExpressions() {
        return Collections.singletonList(expression);
    }

    /**
     * Returns the expression used by this operator possibly completed in subclasses with other parameters.
     * This is used for {@link #toString()}, {@link #hashCode()} and {@link #equals(Object)} implementations.
     */
    @Override
    protected Collection<?> getChildren() {
        return getExpressions();
    }

    /**
     * Filter operator that checks if an expression's value is {@code null}.  A {@code null}
     * is equivalent to no value present. The value 0 is a valid value and is not considered
     * {@code null}.
     */
    static final class IsNull<R> extends UnaryFunction<R,Object>
            implements Filter<R>, Optimization.OnFilter<R>
 {
        /** For cross-version compatibility. */
        private static final long serialVersionUID = 2960285515924533419L;

        /** Creates a new operator. */
        IsNull(final Expression<? super R,?> expression) {
            super(expression);
        }

        @Override public ComparisonOperatorName getOperatorType() {
            return ComparisonOperatorName.PROPERTY_IS_NULL;
        }

        /** Creates a new filter of the same type but different parameters. */
        @Override public Filter<R> recreate(final Expression<? super R, ?>[] effective) {
            return new IsNull<>(effective[0]);
        }

        /** Identification of the operation. */
        @Override protected char symbol() {
            return '∅';
        }

        /** Evaluate this filter on the given object. */
        @Override public boolean test(final R object) {
            return expression.apply(object) == null;
        }
    }

    /**
     * Filter operator that checks if an expression's value is nil.
     * The difference with {@link IsNull} is that a value should exist but
     * cannot be provided for the reason given by {@link #getNilReason()}.
     */
    static final class IsNil<R> extends UnaryFunction<R,Object>
            implements Filter<R>, Optimization.OnFilter<R>
    {
        /** For cross-version compatibility. */
        private static final long serialVersionUID = -7540765433296725888L;

        /** The reason why the value is nil, or {@code null} for accepting any reason. */
        private final String nilReason;

        /** Creates a new operator. */
        IsNil(final Expression<? super R,?> expression, final String nilReason) {
            super(expression);
            this.nilReason = nilReason;
        }

        @Override public ComparisonOperatorName getOperatorType() {
            return ComparisonOperatorName.PROPERTY_IS_NIL;
        }

        /** Creates a new filter of the same type but different parameters. */
        @Override public Filter<R> recreate(final Expression<? super R, ?>[] effective) {
            return new IsNil<>(effective[0], nilReason);
        }

        /** Returns the reason why the value is nil. */
        public Optional<String> getNilReason() {
            return Optional.ofNullable(nilReason);
        }

        /** Evaluate this filter on the given object. */
        @Override public boolean test(final R object) {
            final NilReason value = NilReason.forObject(expression.apply(object));
            if (value     == null) return false;
            if (nilReason == null) return true;
            final String explanation = NilReason.OTHER.equals(value) ? value.getOtherExplanation() : value.toString();
            return nilReason.equalsIgnoreCase(explanation);
        }
    }
}


text:
<component name="libraryTable">
  <library name="crashlytics-core-2.3.5">
    <CLASSES>
      <root url="file://$PROJECT_DIR$/app/build/intermediates/exploded-aar/com.crashlytics.sdk.android/crashlytics-core/2.3.5/res" />
      <root url="jar://$PROJECT_DIR$/app/build/intermediates/exploded-aar/com.crashlytics.sdk.android/crashlytics-core/2.3.5/jars/classes.jar!/" />
    </CLASSES>
    <JAVADOC />
    <SOURCES />
  </library>
</component>


text:
<?php

namespace Sabre\CalDAV\Backend;

use Sabre\VObject;
use Sabre\CalDAV;
use Sabre\DAV;
use Sabre\DAV\Exception\Forbidden;

class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {

    /**
     * We need to specify a max date, because we need to stop *somewhere*
     *
     * On 32 bit system the maximum for a signed integer is 2147483647, so
     * MAX_DATE cannot be higher than date('Y-m-d', 2147483647) which results
     * in 2038-01-19 to avoid problems when the date is converted
     * to a unix timestamp.
     */
    const MAX_DATE = '2038-01-01';

    /**
     * pdo
     *
     * @var \PDO
     */
    protected $pdo;

    /**
     * The table name that will be used for calendars
     *
     * @var string
     */
    public $calendarTableName = 'calendars';

    /**
     * The table name that will be used for calendar objects
     *
     * @var string
     */
    public $calendarObjectTableName = 'calendarobjects';

    /**
     * The table name that will be used for tracking changes in calendars.
     *
     * @var string
     */
    public $calendarChangesTableName = 'calendarchanges';

    /**
     * The table name that will be used inbox items.
     *
     * @var string
     */
    public $schedulingObjectTableName = 'schedulingobjects';

    /**
     * The table name that will be used for calendar subscriptions.
     *
     * @var string
     */
    public $calendarSubscriptionsTableName = 'calendarsubscriptions';

    /**
     * List of CalDAV properties, and how they map to database fieldnames
     * Add your own properties by simply adding on to this array.
     *
     * Note that only string-based properties are supported here.
     *
     * @var array
     */
    public $propertyMap = [
        '{DAV:}displayname'                                   => 'displayname',
        '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
        '{urn:ietf:params:xml:ns:caldav}calendar-timezone'    => 'timezone',
        '{http://apple.com/ns/ical/}calendar-order'           => 'calendarorder',
        '{http://apple.com/ns/ical/}calendar-color'           => 'calendarcolor',
    ];

    /**
     * List of subscription properties, and how they map to database fieldnames.
     *
     * @var array
     */
    public $subscriptionPropertyMap = [
        '{DAV:}displayname'                                           => 'displayname',
        '{http://apple.com/ns/ical/}refreshrate'                      => 'refreshrate',
        '{http://apple.com/ns/ical/}calendar-order'                   => 'calendarorder',
        '{http://apple.com/ns/ical/}calendar-color'                   => 'calendarcolor',
        '{http://calendarserver.org/ns/}subscribed-strip-todos'       => 'striptodos',
        '{http://calendarserver.org/ns/}subscribed-strip-alarms'      => 'stripalarms',
        '{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments',
    ];

    /**
     * Creates the backend
     *
     * @param \PDO $pdo
     */
    function __construct(\PDO $pdo) {

        $this->pdo = $pdo;

    }

    /**
     * Returns a list of calendars for a principal.
     *
     * Every project is an array with the following keys:
     *  * id, a unique id that will be used by other functions to modify the
     *    calendar. This can be the same as the uri or a database key.
     *  * uri. This is just the 'base uri' or 'filename' of the calendar.
     *  * principaluri. The owner of the calendar. Almost always the same as
     *    principalUri passed to this method.
     *
     * Furthermore it can contain webdav properties in clark notation. A very
     * common one is '{DAV:}displayname'.
     *
     * Many clients also require:
     * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set
     * For this property, you can just return an instance of
     * Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet.
     *
     * If you return {http://sabredav.org/ns}read-only and set the value to 1,
     * ACL will automatically be put in read-only mode.
     *
     * @param string $principalUri
     * @return array
     */
    function getCalendarsForUser($principalUri) {

        $fields = array_values($this->propertyMap);
        $fields[] = 'id';
        $fields[] = 'uri';
        $fields[] = 'synctoken';
        $fields[] = 'components';
        $fields[] = 'principaluri';
        $fields[] = 'transparent';

        // Making fields a comma-delimited list
        $fields = implode(', ', $fields);
        $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM " . $this->calendarTableName . " WHERE principaluri = ? ORDER BY calendarorder ASC");
        $stmt->execute([$principalUri]);

        $calendars = [];
        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {

            $components = [];
            if ($row['components']) {
                $components = explode(',', $row['components']);
            }

            $calendar = [
                'id'                                                                 => $row['id'],
                'uri'                                                                => $row['uri'],
                'principaluri'                                                       => $row['principaluri'],
                '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}getctag'                  => 'http://sabre.io/ns/sync/' . ($row['synctoken'] ? $row['synctoken'] : '0'),
                '{http://sabredav.org/ns}sync-token'                                 => $row['synctoken'] ? $row['synctoken'] : '0',
                '{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet($components),
                '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp'         => new CalDAV\Xml\Property\ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'),
            ];

            foreach ($this->propertyMap as $xmlName => $dbName) {
                $calendar[$xmlName] = $row[$dbName];
            }

            $calendars[] = $calendar;

        }

        return $calendars;

    }

    /**
     * Creates a new calendar for a principal.
     *
     * If the creation was a success, an id must be returned that can be used
     * to reference this calendar in other methods, such as updateCalendar.
     *
     * @param string $principalUri
     * @param string $calendarUri
     * @param array $properties
     * @return string
     */
    function createCalendar($principalUri, $calendarUri, array $properties) {

        $fieldNames = [
            'principaluri',
            'uri',
            'synctoken',
            'transparent',
        ];
        $values = [
            ':principaluri' => $principalUri,
            ':uri'          => $calendarUri,
            ':synctoken'    => 1,
            ':transparent'  => 0,
        ];

        // Default value
        $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
        $fieldNames[] = 'components';
        if (!isset($properties[$sccs])) {
            $values[':components'] = 'VEVENT,VTODO';
        } else {
            if (!($properties[$sccs] instanceof CalDAV\Xml\Property\SupportedCalendarComponentSet)) {
                throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet');
            }
            $values[':components'] = implode(',', $properties[$sccs]->getValue());
        }
        $transp = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';
        if (isset($properties[$transp])) {
            $values[':transparent'] = $properties[$transp]->getValue() === 'transparent';
        }

        foreach ($this->propertyMap as $xmlName => $dbName) {
            if (isset($properties[$xmlName])) {

                $values[':' . $dbName] = $properties[$xmlName];
                $fieldNames[] = $dbName;
            }
        }

        $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
        $stmt->execute($values);

        return $this->pdo->lastInsertId();

    }

    /**
     * Updates properties for a calendar.
     *
     * The list of mutations is stored in a Sabre\DAV\PropPatch object.
     * To do the actual updates, you must tell this object which properties
     * you're going to process with the handle() method.
     *
     * Calling the handle method is like telling the PropPatch object "I
     * promise I can handle updating this property".
     *
     * Read the PropPatch documenation for more info and examples.
     *
     * @param string $calendarId
     * @param \Sabre\DAV\PropPatch $propPatch
     * @return void
     */
    function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) {

        $supportedProperties = array_keys($this->propertyMap);
        $supportedProperties[] = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';

        $propPatch->handle($supportedProperties, function($mutations) use ($calendarId) {
            $newValues = [];
            foreach ($mutations as $propertyName => $propertyValue) {

                switch ($propertyName) {
                    case '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' :
                        $fieldName = 'transparent';
                        $newValues[$fieldName] = $propertyValue->getValue() === 'transparent';
                        break;
                    default :
                        $fieldName = $this->propertyMap[$propertyName];
                        $newValues[$fieldName] = $propertyValue;
                        break;
                }

            }
            $valuesSql = [];
            foreach ($newValues as $fieldName => $value) {
                $valuesSql[] = $fieldName . ' = ?';
            }

            $stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?");
            $newValues['id'] = $calendarId;
            $stmt->execute(array_values($newValues));

            $this->addChange($calendarId, "", 2);

            return true;

        });

    }

    /**
     * Delete a calendar and all it's objects
     *
     * @param string $calendarId
     * @return void
     */
    function deleteCalendar($calendarId) {

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?');
        $stmt->execute([$calendarId]);

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarTableName . ' WHERE id = ?');
        $stmt->execute([$calendarId]);

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarChangesTableName . ' WHERE calendarid = ?');
        $stmt->execute([$calendarId]);

    }

    /**
     * Returns all calendar objects within a calendar.
     *
     * Every item contains an array with the following keys:
     *   * calendardata - The iCalendar-compatible calendar data
     *   * uri - a unique key which will be used to construct the uri. This can
     *     be any arbitrary string, but making sure it ends with '.ics' is a
     *     good idea. This is only the basename, or filename, not the full
     *     path.
     *   * lastmodified - a timestamp of the last modification time
     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
     *   '  "abcdef"')
     *   * size - The size of the calendar objects, in bytes.
     *   * component - optional, a string containing the type of object, such
     *     as 'vevent' or 'vtodo'. If specified, this will be used to populate
     *     the Content-Type header.
     *
     * Note that the etag is optional, but it's highly encouraged to return for
     * speed reasons.
     *
     * The calendardata is also optional. If it's not returned
     * 'getCalendarObject' will be called later, which *is* expected to return
     * calendardata.
     *
     * If neither etag or size are specified, the calendardata will be
     * used/fetched to determine these numbers. If both are specified the
     * amount of times this is needed is reduced by a great degree.
     *
     * @param string $calendarId
     * @return array
     */
    function getCalendarObjects($calendarId) {

        $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?');
        $stmt->execute([$calendarId]);

        $result = [];
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
            $result[] = [
                'id'           => $row['id'],
                'uri'          => $row['uri'],
                'lastmodified' => $row['lastmodified'],
                'etag'         => '"' . $row['etag'] . '"',
                'calendarid'   => $row['calendarid'],
                'size'         => (int)$row['size'],
                'component'    => strtolower($row['componenttype']),
            ];
        }

        return $result;

    }

    /**
     * Returns information from a single calendar object, based on it's object
     * uri.
     *
     * The object uri is only the basename, or filename and not a full path.
     *
     * The returned array must have the same keys as getCalendarObjects. The
     * 'calendardata' object is required here though, while it's not required
     * for getCalendarObjects.
     *
     * This method must return null if the object did not exist.
     *
     * @param string $calendarId
     * @param string $objectUri
     * @return array|null
     */
    function getCalendarObject($calendarId, $objectUri) {

        $stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?');
        $stmt->execute([$calendarId, $objectUri]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$row) return null;

        return [
            'id'            => $row['id'],
            'uri'           => $row['uri'],
            'lastmodified'  => $row['lastmodified'],
            'etag'          => '"' . $row['etag'] . '"',
            'calendarid'    => $row['calendarid'],
            'size'          => (int)$row['size'],
            'calendardata'  => $row['calendardata'],
            'component'     => strtolower($row['componenttype']),
         ];

    }

    /**
     * Returns a list of calendar objects.
     *
     * This method should work identical to getCalendarObject, but instead
     * return all the calendar objects in the list as an array.
     *
     * If the backend supports this, it may allow for some speed-ups.
     *
     * @param mixed $calendarId
     * @param array $uris
     * @return array
     */
    function getMultipleCalendarObjects($calendarId, array $uris) {

        $query = 'SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri IN (';
        // Inserting a whole bunch of question marks
        $query .= implode(',', array_fill(0, count($uris), '?'));
        $query .= ')';

        $stmt = $this->pdo->prepare($query);
        $stmt->execute(array_merge([$calendarId], $uris));

        $result = [];
        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {

            $result[] = [
                'id'           => $row['id'],
                'uri'          => $row['uri'],
                'lastmodified' => $row['lastmodified'],
                'etag'         => '"' . $row['etag'] . '"',
                'calendarid'   => $row['calendarid'],
                'size'         => (int)$row['size'],
                'calendardata' => $row['calendardata'],
                'component'    => strtolower($row['componenttype']),
            ];

        }
        return $result;

    }

    /**
     * Creates a new calendar object.
     *
     * The object uri is only the basename, or filename and not a full path.
     *
     * It is possible return an etag from this function, which will be used in
     * the response to this PUT request. Note that the ETag must be surrounded
     * by double-quotes.
     *
     * However, you should only really return this ETag if you don't mangle the
     * calendar-data. If the result of a subsequent GET to this object is not
     * the exact same as this request body, you should omit the ETag.
     *
     * @param mixed $calendarId
     * @param string $objectUri
     * @param string $calendarData
     * @return string|null
     */
    function createCalendarObject($calendarId, $objectUri, $calendarData) {

        $extraData = $this->getDenormalizedData($calendarData);

        $stmt = $this->pdo->prepare('INSERT INTO ' . $this->calendarObjectTableName . ' (calendarid, uri, calendardata, lastmodified, etag, size, componenttype, firstoccurence, lastoccurence, uid) VALUES (?,?,?,?,?,?,?,?,?,?)');
        $stmt->execute([
            $calendarId,
            $objectUri,
            $calendarData,
            time(),
            $extraData['etag'],
            $extraData['size'],
            $extraData['componentType'],
            $extraData['firstOccurence'],
            $extraData['lastOccurence'],
            $extraData['uid'],
        ]);
        $this->addChange($calendarId, $objectUri, 1);

        return '"' . $extraData['etag'] . '"';

    }

    /**
     * Updates an existing calendarobject, based on it's uri.
     *
     * The object uri is only the basename, or filename and not a full path.
     *
     * It is possible return an etag from this function, which will be used in
     * the response to this PUT request. Note that the ETag must be surrounded
     * by double-quotes.
     *
     * However, you should only really return this ETag if you don't mangle the
     * calendar-data. If the result of a subsequent GET to this object is not
     * the exact same as this request body, you should omit the ETag.
     *
     * @param mixed $calendarId
     * @param string $objectUri
     * @param string $calendarData
     * @return string|null
     */
    function updateCalendarObject($calendarId, $objectUri, $calendarData) {

        $extraData = $this->getDenormalizedData($calendarData);

        $stmt = $this->pdo->prepare('UPDATE ' . $this->calendarObjectTableName . ' SET calendardata = ?, lastmodified = ?, etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ?, uid = ? WHERE calendarid = ? AND uri = ?');
        $stmt->execute([$calendarData, time(), $extraData['etag'], $extraData['size'], $extraData['componentType'], $extraData['firstOccurence'], $extraData['lastOccurence'], $extraData['uid'], $calendarId, $objectUri]);

        $this->addChange($calendarId, $objectUri, 2);

        return '"' . $extraData['etag'] . '"';

    }

    /**
     * Parses some information from calendar objects, used for optimized
     * calendar-queries.
     *
     * Returns an array with the following keys:
     *   * etag - An md5 checksum of the object without the quotes.
     *   * size - Size of the object in bytes
     *   * componentType - VEVENT, VTODO or VJOURNAL
     *   * firstOccurence
     *   * lastOccurence
     *   * uid - value of the UID property
     *
     * @param string $calendarData
     * @return array
     */
    protected function getDenormalizedData($calendarData) {

        $vObject = VObject\Reader::read($calendarData);
        $componentType = null;
        $component = null;
        $firstOccurence = null;
        $lastOccurence = null;
        $uid = null;
        foreach ($vObject->getComponents() as $component) {
            if ($component->name !== 'VTIMEZONE') {
                $componentType = $component->name;
                $uid = (string)$component->UID;
                break;
            }
        }
        if (!$componentType) {
            throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
        }
        if ($componentType === 'VEVENT') {
            $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
            // Finding the last occurence is a bit harder
            if (!isset($component->RRULE)) {
                if (isset($component->DTEND)) {
                    $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
                } elseif (isset($component->DURATION)) {
                    $endDate = clone $component->DTSTART->getDateTime();
                    $endDate = $endDate->add(VObject\DateTimeParser::parse($component->DURATION->getValue()));
                    $lastOccurence = $endDate->getTimeStamp();
                } elseif (!$component->DTSTART->hasTime()) {
                    $endDate = clone $component->DTSTART->getDateTime();
                    $endDate = $endDate->modify('+1 day');
                    $lastOccurence = $endDate->getTimeStamp();
                } else {
                    $lastOccurence = $firstOccurence;
                }
            } else {
                $it = new VObject\Recur\EventIterator($vObject, (string)$component->UID);
                $maxDate = new \DateTime(self::MAX_DATE);
                if ($it->isInfinite()) {
                    $lastOccurence = $maxDate->getTimeStamp();
                } else {
                    $end = $it->getDtEnd();
                    while ($it->valid() && $end < $maxDate) {
                        $end = $it->getDtEnd();
                        $it->next();

                    }
                    $lastOccurence = $end->getTimeStamp();
                }

            }
        }

        // Destroy circular references to PHP will GC the object.
        $vObject->destroy();

        return [
            'etag'           => md5($calendarData),
            'size'           => strlen($calendarData),
            'componentType'  => $componentType,
            'firstOccurence' => $firstOccurence,
            'lastOccurence'  => $lastOccurence,
            'uid'            => $uid,
        ];

    }

    /**
     * Deletes an existing calendar object.
     *
     * The object uri is only the basename, or filename and not a full path.
     *
     * @param string $calendarId
     * @param string $objectUri
     * @return void
     */
    function deleteCalendarObject($calendarId, $objectUri) {

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?');
        $stmt->execute([$calendarId, $objectUri]);

        $this->addChange($calendarId, $objectUri, 3);

    }

    /**
     * Performs a calendar-query on the contents of this calendar.
     *
     * The calendar-query is defined in RFC4791 : CalDAV. Using the
     * calendar-query it is possible for a client to request a specific set of
     * object, based on contents of iCalendar properties, date-ranges and
     * iCalendar component types (VTODO, VEVENT).
     *
     * This method should just return a list of (relative) urls that match this
     * query.
     *
     * The list of filters are specified as an array. The exact array is
     * documented by \Sabre\CalDAV\CalendarQueryParser.
     *
     * Note that it is extremely likely that getCalendarObject for every path
     * returned from this method will be called almost immediately after. You
     * may want to anticipate this to speed up these requests.
     *
     * This method provides a default implementation, which parses *all* the
     * iCalendar objects in the specified calendar.
     *
     * This default may well be good enough for personal use, and calendars
     * that aren't very large. But if you anticipate high usage, big calendars
     * or high loads, you are strongly adviced to optimize certain paths.
     *
     * The best way to do so is override this method and to optimize
     * specifically for 'common filters'.
     *
     * Requests that are extremely common are:
     *   * requests for just VEVENTS
     *   * requests for just VTODO
     *   * requests with a time-range-filter on a VEVENT.
     *
     * ..and combinations of these requests. It may not be worth it to try to
     * handle every possible situation and just rely on the (relatively
     * easy to use) CalendarQueryValidator to handle the rest.
     *
     * Note that especially time-range-filters may be difficult to parse. A
     * time-range filter specified on a VEVENT must for instance also handle
     * recurrence rules correctly.
     * A good example of how to interprete all these filters can also simply
     * be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct
     * as possible, so it gives you a good idea on what type of stuff you need
     * to think of.
     *
     * This specific implementation (for the PDO) backend optimizes filters on
     * specific components, and VEVENT time-ranges.
     *
     * @param string $calendarId
     * @param array $filters
     * @return array
     */
    function calendarQuery($calendarId, array $filters) {

        $componentType = null;
        $requirePostFilter = true;
        $timeRange = null;

        // if no filters were specified, we don't need to filter after a query
        if (!$filters['prop-filters'] && !$filters['comp-filters']) {
            $requirePostFilter = false;
        }

        // Figuring out if there's a component filter
        if (count($filters['comp-filters']) > 0 && !$filters['comp-filters'][0]['is-not-defined']) {
            $componentType = $filters['comp-filters'][0]['name'];

            // Checking if we need post-filters
            if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['time-range'] && !$filters['comp-filters'][0]['prop-filters']) {
                $requirePostFilter = false;
            }
            // There was a time-range filter
            if ($componentType == 'VEVENT' && isset($filters['comp-filters'][0]['time-range'])) {
                $timeRange = $filters['comp-filters'][0]['time-range'];

                // If start time OR the end time is not specified, we can do a
                // 100% accurate mysql query.
                if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['prop-filters'] && (!$timeRange['start'] || !$timeRange['end'])) {
                    $requirePostFilter = false;
                }
            }

        }

        if ($requirePostFilter) {
            $query = "SELECT uri, calendardata FROM " . $this->calendarObjectTableName . " WHERE calendarid = :calendarid";
        } else {
            $query = "SELECT uri FROM " . $this->calendarObjectTableName . " WHERE calendarid = :calendarid";
        }

        $values = [
            'calendarid' => $calendarId,
        ];

        if ($componentType) {
            $query .= " AND componenttype = :componenttype";
            $values['componenttype'] = $componentType;
        }

        if ($timeRange && $timeRange['start']) {
            $query .= " AND lastoccurence > :startdate";
            $values['startdate'] = $timeRange['start']->getTimeStamp();
        }
        if ($timeRange && $timeRange['end']) {
            $query .= " AND firstoccurence < :enddate";
            $values['enddate'] = $timeRange['end']->getTimeStamp();
        }

        $stmt = $this->pdo->prepare($query);
        $stmt->execute($values);

        $result = [];
        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
            if ($requirePostFilter) {
                if (!$this->validateFilterForObject($row, $filters)) {
                    continue;
                }
            }
            $result[] = $row['uri'];

        }

        return $result;

    }

    /**
     * Searches through all of a users calendars and calendar objects to find
     * an object with a specific UID.
     *
     * This method should return the path to this object, relative to the
     * calendar home, so this path usually only contains two parts:
     *
     * calendarpath/objectpath.ics
     *
     * If the uid is not found, return null.
     *
     * This method should only consider * objects that the principal owns, so
     * any calendars owned by other principals that also appear in this
     * collection should be ignored.
     *
     * @param string $principalUri
     * @param string $uid
     * @return string|null
     */
    function getCalendarObjectByUID($principalUri, $uid) {

        $query = <<<SQL
SELECT
    calendars.uri AS calendaruri, calendarobjects.uri as objecturi
FROM
    $this->calendarObjectTableName AS calendarobjects
LEFT JOIN
    $this->calendarTableName AS calendars
    ON calendarobjects.calendarid = calendars.id
WHERE
    calendars.principaluri = ?
    AND
    calendarobjects.uid = ?
SQL;

        $stmt = $this->pdo->prepare($query);
        $stmt->execute([$principalUri, $uid]);

        if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
            return $row['calendaruri'] . '/' . $row['objecturi'];
        }

    }

    /**
     * The getChanges method returns all the changes that have happened, since
     * the specified syncToken in the specified calendar.
     *
     * This function should return an array, such as the following:
     *
     * [
     *   'syncToken' => 'The current synctoken',
     *   'added'   => [
     *      'new.txt',
     *   ],
     *   'modified'   => [
     *      'modified.txt',
     *   ],
     *   'deleted' => [
     *      'foo.php.bak',
     *      'old.txt'
     *   ]
     * ];
     *
     * The returned syncToken property should reflect the *current* syncToken
     * of the calendar, as reported in the {http://sabredav.org/ns}sync-token
     * property this is needed here too, to ensure the operation is atomic.
     *
     * If the $syncToken argument is specified as null, this is an initial
     * sync, and all members should be reported.
     *
     * The modified property is an array of nodenames that have changed since
     * the last token.
     *
     * The deleted property is an array with nodenames, that have been deleted
     * from collection.
     *
     * The $syncLevel argument is basically the 'depth' of the report. If it's
     * 1, you only have to report changes that happened only directly in
     * immediate descendants. If it's 2, it should also include changes from
     * the nodes below the child collections. (grandchildren)
     *
     * The $limit argument allows a client to specify how many results should
     * be returned at most. If the limit is not specified, it should be treated
     * as infinite.
     *
     * If the limit (infinite or not) is higher than you're willing to return,
     * you should throw a Sabre\DAV\Exception\TooMuchMatches() exception.
     *
     * If the syncToken is expired (due to data cleanup) or unknown, you must
     * return null.
     *
     * The limit is 'suggestive'. You are free to ignore it.
     *
     * @param string $calendarId
     * @param string $syncToken
     * @param int $syncLevel
     * @param int $limit
     * @return array
     */
    function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null) {

        // Current synctoken
        $stmt = $this->pdo->prepare('SELECT synctoken FROM ' . $this->calendarTableName . ' WHERE id = ?');
        $stmt->execute([ $calendarId ]);
        $currentToken = $stmt->fetchColumn(0);

        if (is_null($currentToken)) return null;

        $result = [
            'syncToken' => $currentToken,
            'added'     => [],
            'modified'  => [],
            'deleted'   => [],
        ];

        if ($syncToken) {

            $query = "SELECT uri, operation FROM " . $this->calendarChangesTableName . " WHERE synctoken >= ? AND synctoken < ? AND calendarid = ? ORDER BY synctoken";
            if ($limit > 0) $query .= " LIMIT " . (int)$limit;

            // Fetching all changes
            $stmt = $this->pdo->prepare($query);
            $stmt->execute([$syncToken, $currentToken, $calendarId]);

            $changes = [];

            // This loop ensures that any duplicates are overwritten, only the
            // last change on a node is relevant.
            while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {

                $changes[$row['uri']] = $row['operation'];

            }

            foreach ($changes as $uri => $operation) {

                switch ($operation) {
                    case 1 :
                        $result['added'][] = $uri;
                        break;
                    case 2 :
                        $result['modified'][] = $uri;
                        break;
                    case 3 :
                        $result['deleted'][] = $uri;
                        break;
                }

            }
        } else {
            // No synctoken supplied, this is the initial sync.
            $query = "SELECT uri FROM " . $this->calendarObjectTableName . " WHERE calendarid = ?";
            $stmt = $this->pdo->prepare($query);
            $stmt->execute([$calendarId]);

            $result['added'] = $stmt->fetchAll(\PDO::FETCH_COLUMN);
        }
        return $result;

    }

    /**
     * Adds a change record to the calendarchanges table.
     *
     * @param mixed $calendarId
     * @param string $objectUri
     * @param int $operation 1 = add, 2 = modify, 3 = delete.
     * @return void
     */
    protected function addChange($calendarId, $objectUri, $operation) {

        $stmt = $this->pdo->prepare('INSERT INTO ' . $this->calendarChangesTableName . ' (uri, synctoken, calendarid, operation) SELECT ?, synctoken, ?, ? FROM ' . $this->calendarTableName . ' WHERE id = ?');
        $stmt->execute([
            $objectUri,
            $calendarId,
            $operation,
            $calendarId
        ]);
        $stmt = $this->pdo->prepare('UPDATE ' . $this->calendarTableName . ' SET synctoken = synctoken + 1 WHERE id = ?');
        $stmt->execute([
            $calendarId
        ]);

    }

    /**
     * Returns a list of subscriptions for a principal.
     *
     * Every subscription is an array with the following keys:
     *  * id, a unique id that will be used by other functions to modify the
     *    subscription. This can be the same as the uri or a database key.
     *  * uri. This is just the 'base uri' or 'filename' of the subscription.
     *  * principaluri. The owner of the subscription. Almost always the same as
     *    principalUri passed to this method.
     *  * source. Url to the actual feed
     *
     * Furthermore, all the subscription info must be returned too:
     *
     * 1. {DAV:}displayname
     * 2. {http://apple.com/ns/ical/}refreshrate
     * 3. {http://calendarserver.org/ns/}subscribed-strip-todos (omit if todos
     *    should not be stripped).
     * 4. {http://calendarserver.org/ns/}subscribed-strip-alarms (omit if alarms
     *    should not be stripped).
     * 5. {http://calendarserver.org/ns/}subscribed-strip-attachments (omit if
     *    attachments should not be stripped).
     * 7. {http://apple.com/ns/ical/}calendar-color
     * 8. {http://apple.com/ns/ical/}calendar-order
     * 9. {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set
     *    (should just be an instance of
     *    Sabre\CalDAV\Property\SupportedCalendarComponentSet, with a bunch of
     *    default components).
     *
     * @param string $principalUri
     * @return array
     */
    function getSubscriptionsForUser($principalUri) {

        $fields = array_values($this->subscriptionPropertyMap);
        $fields[] = 'id';
        $fields[] = 'uri';
        $fields[] = 'source';
        $fields[] = 'principaluri';
        $fields[] = 'lastmodified';

        // Making fields a comma-delimited list
        $fields = implode(', ', $fields);
        $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM " . $this->calendarSubscriptionsTableName . " WHERE principaluri = ? ORDER BY calendarorder ASC");
        $stmt->execute([$principalUri]);

        $subscriptions = [];
        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {

            $subscription = [
                'id'           => $row['id'],
                'uri'          => $row['uri'],
                'principaluri' => $row['principaluri'],
                'source'       => $row['source'],
                'lastmodified' => $row['lastmodified'],

                '{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet(['VTODO', 'VEVENT']),
            ];

            foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
                if (!is_null($row[$dbName])) {
                    $subscription[$xmlName] = $row[$dbName];
                }
            }

            $subscriptions[] = $subscription;

        }

        return $subscriptions;

    }

    /**
     * Creates a new subscription for a principal.
     *
     * If the creation was a success, an id must be returned that can be used to reference
     * this subscription in other methods, such as updateSubscription.
     *
     * @param string $principalUri
     * @param string $uri
     * @param array $properties
     * @return mixed
     */
    function createSubscription($principalUri, $uri, array $properties) {

        $fieldNames = [
            'principaluri',
            'uri',
            'source',
            'lastmodified',
        ];

        if (!isset($properties['{http://calendarserver.org/ns/}source'])) {
            throw new Forbidden('The {http://calendarserver.org/ns/}source property is required when creating subscriptions');
        }

        $values = [
            ':principaluri' => $principalUri,
            ':uri'          => $uri,
            ':source'       => $properties['{http://calendarserver.org/ns/}source']->getHref(),
            ':lastmodified' => time(),
        ];

        foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
            if (isset($properties[$xmlName])) {

                $values[':' . $dbName] = $properties[$xmlName];
                $fieldNames[] = $dbName;
            }
        }

        $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarSubscriptionsTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
        $stmt->execute($values);

        return $this->pdo->lastInsertId();

    }

    /**
     * Updates a subscription
     *
     * The list of mutations is stored in a Sabre\DAV\PropPatch object.
     * To do the actual updates, you must tell this object which properties
     * you're going to process with the handle() method.
     *
     * Calling the handle method is like telling the PropPatch object "I
     * promise I can handle updating this property".
     *
     * Read the PropPatch documenation for more info and examples.
     *
     * @param mixed $subscriptionId
     * @param \Sabre\DAV\PropPatch $propPatch
     * @return void
     */
    function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) {

        $supportedProperties = array_keys($this->subscriptionPropertyMap);
        $supportedProperties[] = '{http://calendarserver.org/ns/}source';

        $propPatch->handle($supportedProperties, function($mutations) use ($subscriptionId) {

            $newValues = [];

            foreach ($mutations as $propertyName => $propertyValue) {

                if ($propertyName === '{http://calendarserver.org/ns/}source') {
                    $newValues['source'] = $propertyValue->getHref();
                } else {
                    $fieldName = $this->subscriptionPropertyMap[$propertyName];
                    $newValues[$fieldName] = $propertyValue;
                }

            }

            // Now we're generating the sql query.
            $valuesSql = [];
            foreach ($newValues as $fieldName => $value) {
                $valuesSql[] = $fieldName . ' = ?';
            }

            $stmt = $this->pdo->prepare("UPDATE " . $this->calendarSubscriptionsTableName . " SET " . implode(', ', $valuesSql) . ", lastmodified = ? WHERE id = ?");
            $newValues['lastmodified'] = time();
            $newValues['id'] = $subscriptionId;
            $stmt->execute(array_values($newValues));

            return true;

        });

    }

    /**
     * Deletes a subscription
     *
     * @param mixed $subscriptionId
     * @return void
     */
    function deleteSubscription($subscriptionId) {

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarSubscriptionsTableName . ' WHERE id = ?');
        $stmt->execute([$subscriptionId]);

    }

    /**
     * Returns a single scheduling object.
     *
     * The returned array should contain the following elements:
     *   * uri - A unique basename for the object. This will be used to
     *           construct a full uri.
     *   * calendardata - The iCalendar object
     *   * lastmodified - The last modification date. Can be an int for a unix
     *                    timestamp, or a PHP DateTime object.
     *   * etag - A unique token that must change if the object changed.
     *   * size - The size of the object, in bytes.
     *
     * @param string $principalUri
     * @param string $objectUri
     * @return array
     */
    function getSchedulingObject($principalUri, $objectUri) {

        $stmt = $this->pdo->prepare('SELECT uri, calendardata, lastmodified, etag, size FROM ' . $this->schedulingObjectTableName . ' WHERE principaluri = ? AND uri = ?');
        $stmt->execute([$principalUri, $objectUri]);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        if (!$row) return null;

        return [
            'uri'          => $row['uri'],
            'calendardata' => $row['calendardata'],
            'lastmodified' => $row['lastmodified'],
            'etag'         => '"' . $row['etag'] . '"',
            'size'         => (int)$row['size'],
         ];

    }

    /**
     * Returns all scheduling objects for the inbox collection.
     *
     * These objects should be returned as an array. Every item in the array
     * should follow the same structure as returned from getSchedulingObject.
     *
     * The main difference is that 'calendardata' is optional.
     *
     * @param string $principalUri
     * @return array
     */
    function getSchedulingObjects($principalUri) {

        $stmt = $this->pdo->prepare('SELECT id, calendardata, uri, lastmodified, etag, size FROM ' . $this->schedulingObjectTableName . ' WHERE principaluri = ?');
        $stmt->execute([$principalUri]);

        $result = [];
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
            $result[] = [
                'calendardata' => $row['calendardata'],
                'uri'          => $row['uri'],
                'lastmodified' => $row['lastmodified'],
                'etag'         => '"' . $row['etag'] . '"',
                'size'         => (int)$row['size'],
            ];
        }

        return $result;

    }

    /**
     * Deletes a scheduling object
     *
     * @param string $principalUri
     * @param string $objectUri
     * @return void
     */
    function deleteSchedulingObject($principalUri, $objectUri) {

        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->schedulingObjectTableName . ' WHERE principaluri = ? AND uri = ?');
        $stmt->execute([$principalUri, $objectUri]);

    }

    /**
     * Creates a new scheduling object. This should land in a users' inbox.
     *
     * @param string $principalUri
     * @param string $objectUri
     * @param string $objectData
     * @return void
     */
    function createSchedulingObject($principalUri, $objectUri, $objectData) {

        $stmt = $this->pdo->prepare('INSERT INTO ' . $this->schedulingObjectTableName . ' (principaluri, calendardata, uri, lastmodified, etag, size) VALUES (?, ?, ?, ?, ?, ?)');
        $stmt->execute([$principalUri, $objectData, $objectUri, time(), md5($objectData), strlen($objectData) ]);

    }

}


text:
use std::iter;

fn main() {
    format!("A number: {}". iter::once(42).next().unwrap());
    //~^ ERROR expected `,`, found `.`

    // Other kind of types are also checked:

    format!("A number: {}" / iter::once(42).next().unwrap());
    //~^ ERROR expected `,`, found `/`

    format!("A number: {}"; iter::once(42).next().unwrap());
    //~^ ERROR expected `,`, found `;`

    // Note: this character is an COMBINING COMMA BELOW unicode char
    format!("A number: {}" ̦ iter::once(42).next().unwrap());
    //~^ ERROR expected `,`, found `iter`
    //~^^ ERROR unknown start of token: \u{326}

    // Here recovery is tested.
    // If the `compile_error!` is emitted, then the parser is able to recover
    // from the incorrect first separator.
    format!("{}". compile_error!("fail"));
    //~^ ERROR expected `,`, found `.`
    //~^^ ERROR fail
}


text:
package com.example.orm.repository;

import com.example.orm.model.LunchMenu;
import com.example.orm.model.Restaurant;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.sql.Timestamp;
import java.util.List;

@Repository
public interface LunchMenuRepository extends CrudRepository<LunchMenu, Long> {

    public List<LunchMenu> findByUpdatedBetween(Timestamp start,Timestamp end);

    public List<LunchMenu> findByRestaurantAndUpdatedBetween(Restaurant restaurant,Timestamp start,Timestamp end);

    public LunchMenu findByRestaurantAndNameAndUpdatedBetween(Restaurant restaurant,String name,Timestamp start,Timestamp end);

    public void deleteByRestaurantAndNameAndUpdatedBetween(Restaurant restaurant,String name,Timestamp start,Timestamp end);

}


text:
#ifndef __itkRegionGrowImageFilter_h
#define __itkRegionGrowImageFilter_h

#include "itkObject.h"
#include "itkImageToImageFilter.h"

namespace itk
{
/** \class RegionGrowImageFilter
 * \brief Base class for RegionGrowImageFilter object
 *
 * itkRegionGrowImageFilter is the base class for the
 * RegionGrowImageFilter objects. It provides
 * the basic function definitons that are inherent to a
 * RegionGrowImageFilter objects.
 * It is templated over the type of input and output image.
 *
 * This object defines the interface for those algorithm that perform
 * feature/object segmentation by merging regions (parts of the image) that
 * are similar in nature based on some metric. As a result parts of the image
 * which belong to the same object gets merged and the region grows.
 *
 * As an example regarding using this class to implementation of advanced
 * region growing algorithm, itkRegionGrowImageFilterKLM class has been
 * derived from this class. The virtual function ApplyRegionGrowImageFilter()
 * provides the interface to the outside world to extend/enhance the scope of
 * the current algorithm or write other region growing algorithms. The
 * function MergeRegions is interface for the operation that merges two
 * regions.
 *
 * The local variable GridSize is used to define
 * the initial small regions that the image is fragmented (atomic
 * regions) into. For an 12 x 12 input image, GridSize set equal
 * to [3, 3] will result in 16 initial regions. The default values are
 * set equal to 2.
 * The user can sets the number of desired regions via the m_MaxNumRegions
 * parameter and the algorithm tries to perform region merging until there
 * are only m_MaxNumRegions. If m_MaxNumRegions is more than the number of
 * initial blocks, no region merging occurs.
 *
 * These blocks are important as the labels associated with these blocks keep
 * changing during the region growing process and at the end, while generating
 * the results, each of these atomic blocks are revisited and the blocks
 * with same labels are considered to belong to the same region.
 *
 * This object supports data handling of multiband images. The object
 * accepts images in vector format, where each pixel is a vector and each
 * element of the vector corresponds to an entry from 1 particular band of
 * a multiband dataset. The input to this object is assumed to be a multiband
 * vector image, and the output is defined by specific algorithm
 * implementation. The second template parameter is used to generate the
 * the output image and can be modified according the algorithm
 * specific output type.
 *
 * We expect the user to provide the input to the routine in vector format.
 * A single band image is treated as a vector image with a single element
 * for every vector.
 *
 * \ingroup RegionGrowingSegmentation
 * \ingroup ITKKLMRegionGrowing
 */
template< class TInputImage, class TOutputImage >
class RegionGrowImageFilter:
  public ImageToImageFilter< TInputImage, TOutputImage >
{
public:
  /** Standard class typedefs. */
  typedef RegionGrowImageFilter                           Self;
  typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass;
  typedef SmartPointer< Self >                            Pointer;
  typedef SmartPointer< const Self >                      ConstPointer;

  /** Run-time type information (and related methods). */
  itkTypeMacro(RegionGrowImageFilter, ImageToImageFilter);

  /** Type definition for the input image. */
  typedef TInputImage                        InputImageType;
  typedef typename TInputImage::Pointer      InputImagePointer;
  typedef typename TInputImage::ConstPointer InputImageConstPointer;

  /** Type definition for the input image pixel type. */
  typedef typename TInputImage::PixelType InputImagePixelType;

  /** Type definition for the output image. */
  typedef TOutputImage                   OutputImageType;
  typedef typename TOutputImage::Pointer OutputImagePointer;

  /** Type definition for the input image pixel type. */
  typedef typename TOutputImage::PixelType OutputImagePixelType;

  /** Type definition for the initial grid. */
  typedef typename TInputImage::SizeType GridSizeType;

  /** Set/Get the initial grid. */
  itkSetMacro(GridSize, GridSizeType);
  itkGetConstReferenceMacro(GridSize, GridSizeType);

  /** Set/Get the number of regions desired. */
  itkSetMacro(MaximumNumberOfRegions, unsigned int);
  itkGetConstReferenceMacro(MaximumNumberOfRegions, unsigned int);

  /** Define a virtual RegionGrowImageFilter function. */
  virtual void ApplyRegionGrowImageFilter() = 0;

  /** Merge two regions. */
  virtual void MergeRegions() = 0;

protected:
  RegionGrowImageFilter();
  ~RegionGrowImageFilter();
  void PrintSelf(std::ostream & os, Indent indent) const;

private:
  RegionGrowImageFilter(const Self &); //purposely not implemented
  void operator=(const Self &);        //purposely not implemented

  unsigned int m_MaximumNumberOfRegions;

  GridSizeType m_GridSize;
}; // class RegionGrowImageFilter
} // namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRegionGrowImageFilter.hxx"
#endif

#endif


text:
package com.opengamma.engine.depgraph;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opengamma.engine.ComputationTargetResolver;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.MemoryUtils;
import com.opengamma.engine.function.CompiledFunctionDefinition;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.ParameterizedFunction;
import com.opengamma.engine.function.exclusion.FunctionExclusionGroup;
import com.opengamma.engine.function.exclusion.FunctionExclusionGroups;
import com.opengamma.engine.function.resolver.CompiledFunctionResolver;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityProvider;
import com.opengamma.engine.target.ComputationTargetReference;
import com.opengamma.engine.target.ComputationTargetResolverUtils;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;

/**
 * Algorithm state. A context object is used by a single job thread. The root context is not used by any builder thread. The synchronization on the collation methods only is therefore sufficient.
 */
/* package */final class GraphBuildingContext {

  private static final Logger s_logger = LoggerFactory.getLogger(GraphBuildingContext.class);

  private static final int MAX_CALLBACK_DEPTH = 16;

  private final DependencyGraphBuilder _builder;
  private Map<ExceptionWrapper, ExceptionWrapper> _exceptions;
  private int _stackDepth;

  public GraphBuildingContext(final DependencyGraphBuilder builder) {
    _builder = builder;
  }

  private DependencyGraphBuilder getBuilder() {
    return _builder;
  }

  // Configuration & resources

  public MarketDataAvailabilityProvider getMarketDataAvailabilityProvider() {
    return getBuilder().getMarketDataAvailabilityProvider();
  }

  public CompiledFunctionResolver getFunctionResolver() {
    return getBuilder().getFunctionResolver();
  }

  public FunctionCompilationContext getCompilationContext() {
    return getBuilder().getCompilationContext();
  }

  public FunctionExclusionGroups getFunctionExclusionGroups() {
    return getBuilder().getFunctionExclusionGroups();
  }

  public CompiledFunctionDefinition getFunctionDefinition(final String functionId) {
    return getBuilder().getFunctionResolver().getFunction(functionId);
  }

  // Operations

  public void submit(final ContextRunnable runnable) {
    getBuilder().addToRunQueue(runnable);
  }

  /**
   * Schedule the task for execution.
   *
   * @param runnable task to execute, not null
   */
  public void run(final ResolveTask runnable) {
    // Run inline unless the stack is full, or the task attempts to defer execution. Only run if the task hasn't been discarded (ie
    // no-one is going to consume its results)
    if (runnable.addRef()) {
      // Added a reference for the run-queue (which will be removed by tryRun)
      if ((++_stackDepth > MAX_CALLBACK_DEPTH) || !runnable.tryRun(this)) {
        submit(runnable);
      }
      _stackDepth--;
    }
  }

  /**
   * Trigger an underlying pump operation. This may happen before returning or be deferred if the stack is past a depth threshold.
   *
   * @param pump underlying operation
   */
  public void pump(final ResolutionPump pump) {
    s_logger.debug("Pumping {}", pump);
    if (++_stackDepth > MAX_CALLBACK_DEPTH) {
      submit(new ResolutionPump.Pump(pump));
    } else {
      pump.pump(this);
    }
    _stackDepth--;
  }

  /**
   * Trigger an underlying close operation. This may happen before returning or be deferred if the stack is past a depth threshold.
   *
   * @param pump underlying operation
   */
  public void close(final ResolutionPump pump) {
    s_logger.debug("Closing {}", pump);
    if (++_stackDepth > MAX_CALLBACK_DEPTH) {
      submit(new ResolutionPump.Close(pump));
    } else {
      pump.close(this);
    }
    _stackDepth--;
  }

  /**
   * Trigger a resolved callback.
   *
   * @param callback callback object
   * @param valueRequirement requirement resolved
   * @param resolvedValue value resolved to
   * @param pump source of the next value
   */
  public void resolved(final ResolvedValueCallback callback, final ValueRequirement valueRequirement, final ResolvedValue resolvedValue, final ResolutionPump pump) {
    s_logger.debug("Resolved {} to {}", valueRequirement, resolvedValue);
    _stackDepth++;
    // Scheduling failure and resolved callbacks from the run queue is a real headache to debug, so always call them inline
    callback.resolved(this, valueRequirement, resolvedValue, pump);
    _stackDepth--;
  }

  /**
   * Trigger a resolution failure.
   *
   * @param callback callback object
   * @param valueRequirement requirement that failed to resolve or for which there are no further resolutions
   * @param failure description of the failure
   */
  public void failed(final ResolvedValueCallback callback, final ValueRequirement valueRequirement, final ResolutionFailure failure) {
    s_logger.debug("Couldn't resolve {}", valueRequirement);
    _stackDepth++;
    // Scheduling failure and resolved callbacks from the run queue is a real headache to debug, so always call them inline
    callback.failed(this, valueRequirement, failure);
    _stackDepth--;
  }

  /**
   * Stores an exception that should be reported to the user. Only store the first copy of an exception; after that increment the count of times that it occurred.
   *
   * @param t exception to store, not null
   */
  public void exception(final Throwable t) {
    s_logger.debug("Caught exception", t);
    if (_exceptions == null) {
      _exceptions = new HashMap<ExceptionWrapper, ExceptionWrapper>();
    }
    ExceptionWrapper.createAndPut(t, _exceptions);
  }

  public ResolvedValueProducer resolveRequirement(final ValueRequirement rawRequirement, final ResolveTask dependent, final Collection<FunctionExclusionGroup> functionExclusion) {
    final ValueRequirement requirement = simplifyType(rawRequirement);
    s_logger.debug("Resolve requirement {}", requirement);
    if ((dependent != null) && dependent.hasParent(requirement)) {
      s_logger.debug("Can't introduce a ValueRequirement loop");
      return null;
    }
    RequirementResolver resolver = null;
    final ResolveTask[] tasks = getTasksResolving(requirement);
    if (tasks != null) {
      int i = 0;
      int l = tasks.length;
      while (i < l) {
        final ResolveTask task = tasks[i];
        if ((dependent == null) || !dependent.hasParent(task)) {
          if ((task.isFinished() && !task.wasRecursionDetected()) || (ObjectUtils.equals(functionExclusion, task.getFunctionExclusion()) && task.hasParentValueRequirements(dependent))) {
            // The task we've found has either already completed, without hitting a recursion constraint. Or
            // the task is identical to the fallback task we'd create naturally. In either case, release everything
            // else and use it.
            for (int j = 0; j < i; j++) {
              tasks[j].release(this);
            }
            for (int j = i + 1; j < l; j++) {
              tasks[j].release(this);
            }
            return task;
          }
          i++;
        } else {
          task.release(this);
          tasks[i] = tasks[--l];
        }
      }
      // Anything left in the array is suitable for use in a RequirementResolver
      if (l > 0) {
        resolver = new RequirementResolver(requirement, dependent, functionExclusion);
        if (l != tasks.length) {
          resolver.setTasks(this, Arrays.copyOf(tasks, l));
        } else {
          resolver.setTasks(this, tasks);
        }
        for (i = 0; i < l; i++) {
          tasks[i].release(this);
        }
      }
    }
    if (resolver != null) {
      resolver.start(this);
      return resolver;
    } else {
      s_logger.debug("Using direct resolution {}/{}", requirement, dependent);
      return getOrCreateTaskResolving(requirement, dependent, functionExclusion);
    }
  }

  public ResolveTask getOrCreateTaskResolving(final ValueRequirement valueRequirement, final ResolveTask parentTask, final Collection<FunctionExclusionGroup> functionExclusion) {
    final ResolveTask newTask = new ResolveTask(valueRequirement, parentTask, functionExclusion);
    do {
      ResolveTask task;
      final Map<ResolveTask, ResolveTask> tasks = getBuilder().getOrCreateTasks(valueRequirement);
      synchronized (tasks) {
        if (tasks.containsKey(null)) {
          // The cache has been flushed
          continue;
        }
        task = tasks.get(newTask);
        if (task == null) {
          newTask.addRef(); // Already got a reference, increment for the collection
          tasks.put(newTask, newTask);
        } else {
          task.addRef(); // Got the task lock, increment so we can return it
        }
      }
      if (task != null) {
        s_logger.debug("Using existing task {}", task);
        newTask.release(this); // Discard local allocation
        return task;
      } else {
        getBuilder().incrementActiveResolveTasks();
        // Don't call run; we want to fork this out to a new worker thread, never call inline
        newTask.addRef(); // Reference held by the run queue
        submit(newTask);
        return newTask;
      }
    } while (true);
  }

  private ResolveTask[] getTasksResolving(final ValueRequirement valueRequirement) {
    do {
      final ResolveTask[] result;
      final Map<ResolveTask, ResolveTask> tasks = getBuilder().getTasks(valueRequirement);
      if (tasks == null) {
        return null;
      }
      synchronized (tasks) {
        if (tasks.containsKey(null)) {
          // The cache has been flushed
          continue;
        }
        result = new ResolveTask[tasks.size()];
        int i = 0;
        for (final ResolveTask task : tasks.keySet()) {
          result[i++] = task;
          task.addRef(); // Got the task lock
        }
      }
      return result;
    } while (true);
  }

  @SuppressWarnings("unchecked")
  public Pair<ResolveTask[], ResolvedValueProducer[]> getTasksProducing(final ValueSpecification valueSpecification) {
    do {
      final MapEx<ResolveTask, ResolvedValueProducer> tasks = getBuilder().getTasks(valueSpecification);
      if (tasks != null) {
        final ResolveTask[] resultTasks;
        final ResolvedValueProducer[] resultProducers;
        synchronized (tasks) {
          if (tasks.containsKey(null)) {
            continue;
          }
          if (tasks.isEmpty()) {
            return null;
          }
          resultTasks = new ResolveTask[tasks.size()];
          resultProducers = new ResolvedValueProducer[tasks.size()];
          int i = 0;
          for (final Map.Entry<ResolveTask, ResolvedValueProducer> task : (Set<Map.Entry<ResolveTask, ResolvedValueProducer>>) tasks.entrySet()) {
            // Don't ref-count the tasks; they're just used for parent comparisons
            resultTasks[i] = task.getKey();
            resultProducers[i++] = task.getValue();
            task.getValue().addRef(); // We're holding the task lock
          }
        }
        return Pairs.of(resultTasks, resultProducers);
      } else {
        return null;
      }
    } while (true);
  }

  /**
   * Fetches an existing resolution of the given value specification.
   *

   * The {@code valueSpecification} parameter must be normalized.
   *
   * @param valueSpecification the specification to search for, not null
   * @return the resolved value, or null if not resolved
   */
  public ResolvedValue getProduction(final ValueSpecification valueSpecification) {
    return getBuilder().getResolvedValue(valueSpecification);
  }

  public static final class ResolutionIterator {

    private final Object _properties;
    private final Object _functions;
    private final int _length;
    private int _index;

    private ResolutionIterator(final Pair<?, ?> values) {
      _properties = values.getFirst();
      _functions = values.getSecond();
      if (_properties instanceof ValueProperties) {
        _length = 1;
      } else {
        _length = ((ValueProperties[]) _properties).length;
      }
      _index = 0;
    }

    public boolean hasNext() {
      return ++_index < _length;
    }

    public ValueProperties getValueProperties() {
      if (_length == 1) {
        return (ValueProperties) _properties;
      } else {
        return ((ValueProperties[]) _properties)[_index];
      }
    }

    public ParameterizedFunction getFunction() {
      if (_length == 1) {
        return (ParameterizedFunction) _functions;
      } else {
        return ((ParameterizedFunction[]) _functions)[_index];
      }
    }

  }

  /**
   * Returns an iterator over previous resolutions (that are present in the dependency graph) on the same target digest for the same value name.
   *
   * @param targetDigest the target's digest, not null
   * @param desiredValue the value requirement name, not null
   * @return any existing resolutions, null if there are none
   */
  public ResolutionIterator getResolutions(final ComputationTargetSpecification targetSpec, final String desiredValue) {
    Pair<?, ?> properties = getBuilder().getResolutions(targetSpec, desiredValue);
    if (properties == null) {
      return null;
    }
    return new ResolutionIterator(properties);
  }

  public void discardTask(final ResolveTask task) {
    // TODO: Could we post "discardTask" tasks to a queue and have them done in batches by a ContextRunnable?
    do {
      final Map<ResolveTask, ResolveTask> tasks = getBuilder().getTasks(task.getValueRequirement());
      if (tasks == null) {
        return;
      }
      synchronized (tasks) {
        if (tasks.containsKey(null)) {
          continue;
        }
        final int rc = task.getRefCount();
        if (rc == 0) {
          // Not referenced by us by definition
          return;
        }
        if (rc != 1) {
          if (!task.isFinished()) {
            // Can't discard this -- something might be waiting on a result from it??
            return;
          }
        }
        final ResolveTask removed = tasks.remove(task);
        if (removed == null) {
          // Task has already been discarded
          return;
        }
        if (removed != task) {
          // Task has already been discarded and replaced by an equivalent; don't discard that
          tasks.put(removed, removed);
          return;
        }
      }
      task.release(this);
      getBuilder().decrementActiveResolveTasks();
    } while (true);
  }

  /**
   * Declares a task that has been created to deliver a potential resolution.
   *

   * The {@code valueSpecification} parameter must be normalized
   *
   * @param valueSpecification the tentative resolution the value producer will attempt to deliver, not null
   * @param task the task to perform the resolution, not null
   * @param producer the value producer managed by the task which will deliver the value specification, not null
   * @return an existing producer, otherwise null if the new task is now declared for the work
   */
  public ResolvedValueProducer declareTaskProducing(final ValueSpecification valueSpecification, final ResolveTask task, final ResolvedValueProducer producer) {
    do {
      final MapEx<ResolveTask, ResolvedValueProducer> tasks = getBuilder().getOrCreateTasks(valueSpecification);
      ResolvedValueProducer result = null;
      if (tasks != null) {
        ResolvedValueProducer discard = null;
        synchronized (tasks) {
          if (!tasks.isEmpty()) {
            if (tasks.containsKey(null)) {
              continue;
            }
            final Map.Entry<ResolveTask, ResolvedValueProducer> resolveTask = tasks.getHashEntry(task);
            if (resolveTask != null) {
              if (resolveTask.getKey() == task) {
                // Replace an earlier attempt from this task with the new producer
                discard = resolveTask.getValue();
                producer.addRef(); // The caller already holds an open reference
                resolveTask.setValue(producer);
                result = producer;
              } else {
                // An equivalent task is doing the work
                result = resolveTask.getValue();
              }
              result.addRef(); // Either the caller holds an open reference on the producer, or we've got the task lock
            }
          }
          if (result == null) {
            final ResolvedValue value = getBuilder().getResolvedValue(valueSpecification);
            if (value != null) {
              result = new SingleResolvedValueProducer(task.getValueRequirement(), value);
            }
          }
          if (result == null) {
            // No matching tasks
            producer.addRef(); // Caller already holds open reference
            tasks.put(task, producer);
            result = producer;
            result.addRef(); // Caller already holds open reference (this is the producer)
          }
        }
        if (discard != null) {
          discard.release(this);
        }
      } else {
        final ResolvedValue value = getBuilder().getResolvedValue(valueSpecification);
        if (value != null) {
          result = new SingleResolvedValueProducer(task.getValueRequirement(), value);
        }
      }
      return result;
    } while (true);
  }

  public void discardTaskProducing(final ValueSpecification valueSpecification, final ResolveTask task) {
    do {
      final MapEx<ResolveTask, ResolvedValueProducer> tasks = getBuilder().getTasks(valueSpecification);
      if (tasks != null) {
        final ResolvedValueProducer producer;
        synchronized (tasks) {
          if (tasks.containsKey(null)) {
            continue;
          }
          producer = (ResolvedValueProducer) tasks.remove(task);
          if (producer == null) {
            // Wasn't in the set
            return;
          }
        }
        producer.release(this);
      }
      return;
    } while (true);
  }

  public void declareProduction(final ResolvedValue resolvedValue) {
    getBuilder().addResolvedValue(resolvedValue);
  }

  public ComputationTargetSpecification resolveTargetReference(final ComputationTargetReference reference) {
    return getBuilder().resolveTargetReference(reference);
  }

  /**
   * Simplifies the type based on the associated {@link ComputationTargetResolver}.
   *

   * This returns a normalized form of the value specification.
   *
   * @param valueSpec the specification to process, not null
   * @return the possibly simplified specification, not null
   */
  public ValueSpecification simplifyType(final ValueSpecification valueSpec) {
    final ComputationTargetSpecification oldTargetSpec = valueSpec.getTargetSpecification();
    final ComputationTargetSpecification newTargetSpec = ComputationTargetResolverUtils.simplifyType(oldTargetSpec, getCompilationContext().getComputationTargetResolver());
    if (newTargetSpec == oldTargetSpec) {
      return MemoryUtils.instance(valueSpec);
    } else {
      return MemoryUtils.instance(new ValueSpecification(valueSpec.getValueName(), newTargetSpec, valueSpec.getProperties()));
    }
  }

  /**
   * Bulk form of {@link #simplifyType(ValueSpecification)}. If the values are already in their simplified form then the original collection is returned.
   *
   * @param specifications the specifications to process, not null
   * @return the possibly simplified specifications, not null
   */
  public Collection<ValueSpecification> simplifyTypes(final Collection<ValueSpecification> specifications) {
    if (specifications.size() == 1) {
      final ValueSpecification specification = specifications.iterator().next();
      final ValueSpecification reducedSpecification = simplifyType(specification);
      if (specification == reducedSpecification) {
        return specifications;
      } else {
        return Collections.singleton(reducedSpecification);
      }
    } else {
      final Collection<ValueSpecification> result = new ArrayList<ValueSpecification>(specifications.size());
      for (ValueSpecification specification : specifications) {
        result.add(simplifyType(specification));
      }
      return result;
    }
  }

  /**
   * Simplifies the type based on the associated {@link ComputationTargetResolver}.
   *
   * @param valueReq the requirement to process, not null
   * @return the possibly simplified requirement, not null
   */
  public ValueRequirement simplifyType(final ValueRequirement valueReq) {
    final ComputationTargetReference oldTargetRef = valueReq.getTargetReference();
    final ComputationTargetReference newTargetRef = ComputationTargetResolverUtils.simplifyType(oldTargetRef, getCompilationContext().getComputationTargetResolver());
    if (newTargetRef == oldTargetRef) {
      return valueReq;
    } else {
      return MemoryUtils.instance(new ValueRequirement(valueReq.getValueName(), newTargetRef, valueReq.getConstraints()));
    }
  }

  // Failure reporting

  public ResolutionFailure recursiveRequirement(final ValueRequirement valueRequirement) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.recursiveRequirement(valueRequirement);
    }
  }

  public ResolutionFailure functionApplication(final ValueRequirement valueRequirement, final ParameterizedFunction function, final ValueSpecification outputSpecification) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.functionApplication(valueRequirement, function, outputSpecification);
    }
  }

  public ResolutionFailure noFunctions(final ValueRequirement valueRequirement) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.noFunctions(valueRequirement);
    }
  }

  public ResolutionFailure couldNotResolve(final ValueRequirement valueRequirement) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.couldNotResolve(valueRequirement);
    }
  }

  public ResolutionFailure unsatisfied(final ValueRequirement valueRequirement) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.unsatisfied(valueRequirement);
    }
  }

  public ResolutionFailure marketDataMissing(final ValueRequirement valueRequirement) {
    if (getBuilder().isDisableFailureReporting()) {
      return NullResolutionFailure.INSTANCE;
    } else {
      return ResolutionFailureImpl.marketDataMissing(valueRequirement);
    }
  }

  // Collation

  /**
   * Merge information from the other context into this (a root context). The caller must be the thread that was working with the other context.
   *
   * @param context the other context
   */
  public synchronized void mergeThreadContext(final GraphBuildingContext context) {
    if (_exceptions == null) {
      _exceptions = new HashMap<ExceptionWrapper, ExceptionWrapper>();
    }
    if (context._exceptions != null) {
      for (final ExceptionWrapper exception : context._exceptions.keySet()) {
        final ExceptionWrapper existing = _exceptions.get(exception);
        if (existing != null) {
          existing.incrementCount(exception.getCount());
        } else {
          _exceptions.put(exception, exception);
        }
      }
    }
  }

  public synchronized Map<Throwable, Integer> getExceptions() {
    if (_exceptions == null) {
      return Collections.emptyMap();
    }
    final Map<Throwable, Integer> result = new HashMap<Throwable, Integer>();
    for (final ExceptionWrapper exception : _exceptions.keySet()) {
      result.put(exception.getException(), exception.getCount());
    }
    return result;
  }

}