text:
package org.encog.ml.bayesian.parse;

import java.util.ArrayList;
import java.util.List;

import org.encog.ml.bayesian.BayesianChoice;
import org.encog.ml.bayesian.BayesianError;
import org.encog.ml.bayesian.BayesianEvent;

/**
 * A parsed event.
 */
public class ParsedEvent {
	/**
	 * The event label.
	 */
	private final String label;

	/**
	 * The event value.
	 */
	private String value;

	/**
	 * The choices.
	 */
	private final List<ParsedChoice> list = new ArrayList<ParsedChoice>();

	/**
	 * Construct a parsed even with the specified label.
	 * @param theLabel
	 */
	public ParsedEvent(String theLabel) {
		this.label = theLabel;
	}

	/**
	 * @return The value for this event, or null if undefined.
	 */
	public String getValue() {
		return value;
	}

	/**
	 * Set the value for this event.
	 * @param value The value for this event.
	 */
	public void setValue(String value) {
		this.value = value;
	}

	/**
	 * @return The label for this event.
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * Resolve the event to an actual value.
	 * @param actualEvent The actual event.
	 * @return The value.
	 */
	public int resolveValue(BayesianEvent actualEvent) {
		int result = 0;

		if( this.value==null ) {
			throw new BayesianError("Value is undefined for " + this.label + " should express a value with +, - or =.");
		}

		for(BayesianChoice choice: actualEvent.getChoices()) {
			if( this.value.equals(choice.getLabel())) {
				return result;
			}
			result++;
		}

		// resolve true/false if not found, probably came from +/- notation
		if( this.value.equalsIgnoreCase("true")) {
			return 0;
		} else if( this.value.equalsIgnoreCase("false")) {
			return 1;
		}

		// try to resolve numeric index
		try {
			int i = Integer.parseInt(this.value);
			if( i<actualEvent.getChoices().size() ) {
				return i;
			}
		} catch(NumberFormatException ex) {
			// well, we tried
		}

		// error out if nothing found
		throw new BayesianError("Can'f find choice " + this.value + " in the event " + this.label );
	}

	/**
	 * @return A list of choices.
	 */
	public List<ParsedChoice> getList() {
		return list;
	}

	/**
	 * {@inheritDoc}
	 */
	public String toString() {
		StringBuilder result = new StringBuilder();
		result.append("[ParsedEvent:label=");
		result.append(this.label);
		result.append(",value=");
		result.append(this.value);
		result.append("]");
		return result.toString();
	}

}


text:
<!DOCTYPE html>
<html>
<head>
	<title>Panels</title>
	<!-- -->
	<meta name="apple-mobile-web-app-capable" content="yes" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
	<!-- -->
	<script src="../../../../enyo/enyo.js" type="text/javascript"></script>
	<script src="../../../../lib/onyx/package.js" type="text/javascript"></script>
	<script src="../../../../lib/layout/package.js" type="text/javascript"></script>
	<script src="../package.js" type="text/javascript"></script>
	<!-- -->
	<style>
		.panels {
			height: 33%;
			width: 33%;
			min-height: 320px;
			min-width: 320px;
			display: inline-block;
			margin: 30px;
			border: 10px solid orange;
		}

		.panels > * {
			border: 2px solid #333;
			font-size: 5em;
			text-align: center;
		}

		.wide > * {
			min-width: 50%;
		}

		/* IE8 panel height hack */
		@media \0screen {
			.panels {
				height: 320px;
				min-height: 0px;
			}
		}

	</style>
</head>
<body>
	<script>
		enyo.kind({
			name: "SamplePanels",
			kind: "Panels",
			classes: "panels enyo-border-box",
			components: [
				{content: 0, style: "background: red;"},
				{content: 1, style: "background: orange;"},
				{content: 2, style: "background: yellow;"},
				{content: 3, style: "background: green;"},
				{content: 4, style: "background: blue;"},
				{content: 5, style: "background: indigo;" },
				{content: 6, style: "background: violet;", fit: true}
			]
		});

		enyo.kind({
			name: "App",
			kind: "FittableRows",
			components: [
				{kind: "onyx.Toolbar", components: [
					{kind: "onyx.Button", content: "Previous", ontap: "prevPanel"},
					{kind: "onyx.Button", content: "Next", ontap: "nextPanel"},
					{kind: "onyx.InputDecorator", components: [
						{kind: "onyx.Input", value: 4, onchange: "gotoPanel"}
					]},
					{kind: "onyx.Button", content: "Go", ontap: "gotoPanel"},
				]},
				{name: "samples", kind: "Scroller", fit: true, components: [
					{kind: "SamplePanels", arrangerKind: "CardArranger", onTransitionStart: "transitionStart", onTransitionFinish: "transitionFinish"},
					{kind: "SamplePanels", arrangerKind: "CardSlideInArranger"},
					{kind: "SamplePanels", arrangerKind: "CarouselArranger", classes: "wide", style: "width: 80%;"},
					{kind: "SamplePanels", arrangerKind: "CollapsingArranger", style: "width: 80%;"},
					{kind: "SamplePanels", arrangerKind: "LeftRightArranger", wrap: true},
					{kind: "SamplePanels", arrangerKind: "TopBottomArranger", wrap: true},
					{kind: "SamplePanels", arrangerKind: "SpiralArranger", wrap: true},
					{kind: "SamplePanels", arrangerKind: "GridArranger", wrap: true}
				]}
			],
			prevPanel: function() {
				this.forEachPanel("previous");
			},
			nextPanel: function() {
				this.forEachPanel("next");
			},
			gotoPanel: function() {
				var i = Number(this.$.input.getValue());
				this.forEachPanel("setIndex", i);
			},
			forEachPanel: function(inMethod) {
				var c$ = this.$.samples.getClientControls();
				var a = enyo.cloneArray(arguments, 1) || [];
				for (var i=0, c; c=c$[i]; i++) {
					c[inMethod].apply(c, a);
				}
			},
			transitionStart: function(inSender, inEvent) {
				this.log(inEvent.fromIndex, inEvent.toIndex);
			},
			transitionFinish: function(inSender, inEvent) {
				this.log(inEvent.fromIndex, inEvent.toIndex);
			}
		});
		new App({fit: true, classes: "enyo-unselectable"}).write();
	</script>
</body>
</html>

redpajama_set_name: RedPajamaGithub


text:
ape.infrastructure.baseclass.BaseThreadClass
============================================

.. currentmodule:: ape.infrastructure.baseclass

.. autoclass:: BaseThreadClass

   .. automethod:: __init__

   .. rubric:: Methods

   .. autosummary::

      ~BaseThreadClass.__init__
      ~BaseThreadClass.log_error
      ~BaseThreadClass.run
      ~BaseThreadClass.run_thread

   .. rubric:: Attributes

   .. autosummary::

      ~BaseThreadClass.logger
      ~BaseThreadClass.thread


text:
FROM ubuntu:14.04

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    curl \
    gcc \
    git \
    make

# Install Go
ENV GO_VERSION 1.4.2
ENV OS linux
ENV ARCH amd64
# Download and extract the binary to /usr/local/go/{src,bin,pkg}
RUN curl -sSL https://storage.googleapis.com/golang/go$GO_VERSION.$OS-$ARCH.tar.gz \
    | tar -v -C /usr/local/ -xz && \
    mkdir -p /go/bin
ENV PATH /go/bin:/usr/local/go/bin:$PATH
ENV GOPATH /go

# Mount you $GOPATH/src directory
VOLUME /go/src
WORKDIR /go/src


text:
namespace PacketHandlers::HInit
{

void Main(sf::Packet &packet, std::array<intptr_t, 4> data_ptr)
{
    Client *client = (Client *)data_ptr[0];

    if(client->state != Client::State::Uninitialized) return;

    std::array<int, 3> version = { 0, 0, 0 };

    for(int i = 0; i < 3; ++i)
    {
        packet >> version[i];
    }

    bool valid = true;

    for(int i = 0; i < 3; ++i)
    {
        if(version[i] != Server().GetClientVersion()[i]) valid = false;
    }

    unsigned char answer = 0;

    if(valid)
    {
        answer = 1;

        client->state = Client::State::Initialized;
        client->packet_handler.Register(PacketID::Ping, PacketHandlers::HPing::Main, data_ptr);
        client->packet_handler.Register(PacketID::Login, PacketHandlers::HLogin::Main, data_ptr);
        client->packet_handler.Register(PacketID::Account, PacketHandlers::HAccount::Main, data_ptr);
    }
    else
    {
        answer = 2;
    }

    sf::Packet reply;
    reply << (unsigned char)PacketID::Init;
    reply << answer;
    client->Send(reply);
}

}


text:
package gov.nih.nci.caadapter.ui.common.functions;

import gov.nih.nci.caadapter.common.Log;
import gov.nih.nci.caadapter.common.function.FunctionManager;
import gov.nih.nci.caadapter.common.function.meta.FunctionMeta;
import gov.nih.nci.caadapter.ui.common.nodeloader.FunctionMetaNodeLoader;
import gov.nih.nci.caadapter.ui.common.tree.TreeDefaultDragTransferHandler;

import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.BorderLayout;
import java.awt.dnd.DnDConstants;

/**
 * This class displays a scrollable panel listing functions available in FunctionMetaImpl and organizes by Group name.
 *
 * @author OWNER: Scott Jiang
 * @author LAST UPDATE $Author: phadkes $
 * @version Since caAdapter v1.2
 *          revision    $Revision: 1.2 $
 *          date        $Date: 2008-06-09 19:53:51 $
 */
public class FunctionLibraryPane extends JPanel// implements TreeSelectionListener
{
	private JTree tree;
	/**
	 * Creates a Function Library tree and adds it to a panel for display.
	 *
	 * @@param lstFunction a FunctionMetaIml object
	 */
	public FunctionLibraryPane()
	{
		initialize();
	}

	public JTree getFunctionTree()
	{
		return tree;
	}

	private void initialize()
	{
		//set the default layout
        this.setLayout(new BorderLayout());
		//Create the nodes.
		FunctionMetaNodeLoader nodeLoader = new FunctionMetaNodeLoader();
		try
		{
			DefaultMutableTreeNode kindNode = (DefaultMutableTreeNode) nodeLoader.loadData(FunctionManager.getInstance());//new DefaultMutableTreeNode(Config.FUNCTION_DEFINITION_DEFAULT_KIND);

			//Create a tree that allows one selection at a time.
			tree = new JTree(kindNode);
			tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
			new TreeDefaultDragTransferHandler(tree, DnDConstants.ACTION_LINK);

			//Create the scroll pane and add the tree to it.
			JScrollPane treeView = new JScrollPane(tree);
			//Add treeView to this panel.
			this.add(treeView, BorderLayout.CENTER);
		}
		catch(Throwable e)
		{
			Log.logException(getClass(), e);
		}
	}

	/**
	 * Return the user selection of a give function. If nothing is selected, will return null.
	 * @return
	 */
	public FunctionMeta getFunctionSelection()
	{
		FunctionMeta result = null;
		TreePath treePath = tree.getSelectionPath();
		if(treePath!=null)
		{
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
			result = (FunctionMeta) node.getUserObject();
		}
		return result;
	}

	/*** FOLLOWING ARE FOR TEST ONLY WRITTEN BY Jayfus ******************************************************/
	//Optionally set the look and feel.
	private static boolean useSystemLookAndFeel = false;

	/**
	 * Create the GUI and show it.  For thread safety,
	 * this method should be invoked from the
	 * event-dispatching thread.
	 */
	private static void createAndShowGUI()
	{
		if (useSystemLookAndFeel)
		{
			try
			{
				UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			}
			catch (Exception e)
			{
				System.err.println("Couldn't use system look and feel.");
			}
		}

		//Make sure we have nice window decorations.
		JFrame.setDefaultLookAndFeelDecorated(true);

		//Create and set up the window.
		JFrame frame = new JFrame("Function Window Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		//Create and set up the content pane.
		FunctionLibraryPane newContentPane = new FunctionLibraryPane();
		newContentPane.setOpaque(true); //content panes must be opaque
		frame.setContentPane(newContentPane);

		//Display the window.
		frame.pack();
		frame.setVisible(true);
	}

	public static void main(String[] args)
	{
		//Schedule a job for the event-dispatching thread:
		//creating and showing this application's GUI.
		javax.swing.SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				createAndShowGUI();
			}
		});
	}
}
/**
 * HISTORY      : $Log: not supported by cvs2svn $
 * HISTORY      : Revision 1.1  2007/04/03 16:17:14  wangeug
 * HISTORY      : initial loading
 * HISTORY      :
 * HISTORY      : Revision 1.15  2006/10/03 14:45:08  jayannah
 * HISTORY      : Changed the package name to point to
 * HISTORY      :             "gov.nih.nci.caadapter.ui.main.functions"
 * HISTORY      :     from "gov.nih.nci.caadapter.ui.main.jgraph"
 * HISTORY      :
 * HISTORY      : Revision 1.14  2006/08/02 18:44:21  jiangsc
 * HISTORY      : License Update
 * HISTORY      :
 * HISTORY      : Revision 1.13  2006/06/13 18:12:12  jiangsc
 * HISTORY      : Upgraded to catch Throwable instead of Exception.
 * HISTORY      :
 * HISTORY      : Revision 1.12  2006/01/03 19:16:52  jiangsc
 * HISTORY      : License Update
 * HISTORY      :
 * HISTORY      : Revision 1.11  2006/01/03 18:56:24  jiangsc
 * HISTORY      : License Update
 * HISTORY      :
 * HISTORY      : Revision 1.10  2005/12/29 23:06:16  jiangsc
 * HISTORY      : Changed to latest project name.
 * HISTORY      :
 * HISTORY      : Revision 1.9  2005/12/14 21:37:19  jiangsc
 * HISTORY      : Updated license information
 * HISTORY      :
 * HISTORY      : Revision 1.8  2005/11/29 16:23:56  jiangsc
 * HISTORY      : Updated License
 * HISTORY      :
 * HISTORY      : Revision 1.7  2005/10/25 22:00:43  jiangsc
 * HISTORY      : Re-arranged system output strings within UI packages.
 * HISTORY      :
 * HISTORY      : Revision 1.6  2005/07/27 22:41:15  jiangsc
 * HISTORY      : Consolidated context sensitive menu implementation.
 * HISTORY      :
 * HISTORY      : Revision 1.5  2005/07/22 20:53:15  jiangsc
 * HISTORY      : Structure change and added License and history anchors.
 * HISTORY      :
 */


text:
package de.fhopf.lucenesolrtalk.solr;

import com.google.common.collect.Collections2;
import de.fhopf.lucenesolrtalk.Talk;
import de.fhopf.lucenesolrtalk.TalkFromFile;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrInputDocument;

import java.io.File;
import java.io.IOException;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.impl.HttpSolrServer;

/**
 * Indexes files in Solr.
 */
public class Indexer {

    private final SolrServer server;

    private final Log log = LogFactory.getLog(Indexer.class);

    public Indexer(SolrServer server) {
        this.server = server;
    }

    public void index(Collection<Talk> talks) throws IOException, SolrServerException {
        // TODO could also be transformed using guava
        List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
        for (Talk talk: talks) {
            SolrInputDocument doc = new SolrInputDocument();
            doc.addField("path", talk.path);
            doc.addField("title", talk.title);
            doc.addField("date", talk.date);
            doc.addField("content", talk.content);
            doc.addField("organizer", talk.organizer);
            for (String category: talk.categories) {
                doc.addField("category", category);
            }
            for (String speaker: talk.speakers) {
                doc.addField("speaker", speaker);
            }
            docs.add(doc);
        }

        server.add(docs);
        server.commit();
    }

    public void clearIndex() throws SolrServerException, IOException {
        server.deleteByQuery("*:*");
    }

    public static void main(String [] args) throws IOException, SolrServerException {

        if (args.length != 2) {
            System.out.println("Usage: java " + Indexer.class.getCanonicalName() + " <solrUrl> <dataDir>");
            System.exit(-1);
        }

        SolrServer server = new HttpSolrServer(args[0]);

        List<File> files = Arrays.asList(new File(args[1]).listFiles());

        Collection<Talk> talks = Collections2.transform(files, new TalkFromFile());

        Indexer indexer = new Indexer(server);
        indexer.clearIndex();
        indexer.index(talks);
    }

}


text:
/**
 * Utility classes for encoding.
 */
package net.lecousin.framework.encoding;


text:
<?php
  $meta = get_post_meta($post->ID);
  $resources = get_post_meta($post->ID, '_cmb_resources', true);
  $transcript = get_post_meta($post->ID, '_cmb_transcript', true);

  if (!empty($meta['bitly_url'])) {
    $share_url = $meta['bitly_url'][0];
  } else {
    $share_url = get_the_permalink($post->ID);
  }

  $show_category = get_child_level_child_category($post->ID);

  if ($show_category && get_term_meta($show_category->term_id, '_nm_podcast_url', true)) {
    $podcast_url = get_term_meta($show_category->term_id, '_nm_podcast_url', true);
  } else {
    $podcast_url = 'https://podfollow.com/novaramedia/view';
  }
?>

<?php the_title(); ?>

    <?php the_post_thumbnail('col4', ['class' => 'margin-top-small only-desktop']); ?>

    <?php the_content(); ?>

Published <?php the_time('j F Y'); ?>

      <?php
        if (!empty($resources)) {
          echo '
Resources
';
        }
      ?>

<a href="<?php echo $podcast_url; ?>" target="_blank" rel="nofollow">Subscribe to Podcast

    <?php
      if (!empty($meta['_cmb_dl_mp3'])) {
        echo '
Download mp3
';
      }
    ?>

<?php render_tweet_link($share_url, $post->post_title, 'Tweet episode'); ?>

<?php render_facebook_share_link($share_url, 'Share this episode on Facebook'); ?>

<?php render_email_share_link($share_url, $post->post_title, 'Email this episode');?>

<?php render_reddit_share_link($share_url, $post->post_title, 'Post to Reddit');?>

<?php
  if (!empty($resources)) {
    render_resources_row($resources);
  }
?>

<div class="flex-grid-row <?php if (empty($transcript)) { echo 'margin-bottom-large'; } else { echo 'margin-bottom-basic'; } ?>">

    <?php
      if (!empty($meta['_cmb_sc'][0])) {
    ?>
        <iframe src="https://w.soundcloud.com/player/?url=<?php echo urlencode($meta['_cmb_sc'][0]); ?>" width="100%" height="200" scrolling="no" frameborder="no">

      <?php
        if (!empty($meta['_cmb_is_resonance']) && $meta['_cmb_is_resonance'][0]) {
      ?>

        	powered by: Resonance FM

      <?php
        }
      } else {
        echo 'Someone messed up :/';
      }
    ?>

<?php
  if (!empty($transcript)) {
?>

Transcript

      <?php echo apply_filters('the_content', $transcript); ?>

<?php
  }
?>


text:
// Copyright (C) 2013 Frank Raiser
// See the LICENCE file distributed with this work for additional
// information regarding copyright ownership.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scala.logic.disjoint

import scala.annotation.tailrec

/**
 * This class implements a disjoint-sets algorithm with
 * union-by-rank and path compression. The forest/sets/etc. are
 * internal data structures not exposed to the outside. Instead,
 * it is possible to add new elements (which end up in a newly
 * created set), union two elements, and hence, their sets, and
 * find the representative of a disjoint-set by a given element of
 * the set.
 *
 * Objects of this class are almost immutable. All operations
 * return a new updated object. To implement path compression, however,
 * a map with the compressed paths is kept separately.
 *
 * @author Frank Raiser
 */
class DisjointSets[T](val nodes: Map[T, Node[T]] = Map.empty) extends Equals {

  private var compressedPaths : scala.collection.mutable.Map[T, T] =
    scala.collection.mutable.Map.empty

  // scalastyle:off
  // I deem + symbols appropriate operators for adding to a set structure
  def + (element : T) : DisjointSets[T] = add(element)
  def ++(elements : Seq[T]) : DisjointSets[T] = addAll(elements)
  // scalastyle:on

  def add(element : T) : DisjointSets[T] =
    new DisjointSets(nodes + (element -> Node(element, 0, None)) )

  def addAll(elements : Seq[T]) : DisjointSets[T] =
    new DisjointSets(nodes ++ elements.map(e => e -> Node(e, 0, None)) )

  private def createDisjointSetsWithUpdatedNodesAndCompressedPaths(
      updates : List[(Node[T], Node[T])]) : DisjointSets[T] = {
    val updatedNodes = nodes ++ (updates.map(p => p._2.elem -> p._2))
    val ds = new DisjointSets(updatedNodes)
    ds.compressedPaths ++= this.compressedPaths
    ds
  }

  @tailrec
  final def getRepresentativeOfSet(elem : T): Node[T] = {
    val node = nodes.get(elem)
    require(node.isDefined, "element must be in disjoint sets")
    node.get.parent match {
      case None => node.get
      case Some(parentElem) =>
        getRepresentativeOfSet(parentElem)
    }
  }

  def union(elem1 : T, elem2 : T) : DisjointSets[T] = synchronized {
    require(nodes.contains(elem1) && nodes.contains(elem2),
        "Only elements contained in the disjoint-sets can be unioned")
    require(elem1 != elem2, "Only different elements can be unioned")

    val p = (getRepresentativeOfSet(elem1), getRepresentativeOfSet(elem2))
    // we are guaranteed to find the two nodes in the map,
    // and the below cases cover all possibilities
    (p : @unchecked) match {

      // Case #1: both elements already in same set
      case (n1, n2) if n1 == n2 =>
        createDisjointSetsWithUpdatedNodesAndCompressedPaths(List())

      // Case #2: rank1 > rank2 -> make n1 parent of n2
      case (n1 @ Node(_, rank1, _),
            n2 @ Node(_, rank2, _)) if rank1 > rank2 =>
        createDisjointSetsWithUpdatedNodesAndCompressedPaths(List(
            (n2 -> n2.copy(parent = Some(n1.elem)))))

      // Case #3: rank1 < rank2 -> make n2 parent of n1
      case (n1 @ Node(_, rank1, _),
            n2 @ Node(_, rank2, _)) if rank1 < rank2 =>
        createDisjointSetsWithUpdatedNodesAndCompressedPaths(List(
            (n1 -> n1.copy(parent = Some(n2.elem)))))

      // Case #4: rank1 == rank2 -> keep n1 as representative and increment rank
      case (n1 @ Node(_, rank1, _),
            n2 @ Node(_, rank2, _)) /*if rank1 == rank2*/ =>
        val newn1 = n1.copy(rank = rank1 + 1)
        createDisjointSetsWithUpdatedNodesAndCompressedPaths(List(
            (n1 -> newn1),
            (n2 -> n2.copy(parent = Some(newn1.elem)))))
    }
  }

  def find(elem : T) : Option[T] = synchronized {
    val startNode = compressedPaths.get(elem).map(nodes.get(_)) match {
      case Some(node) => node
      case _ => nodes.get(elem)
    }

    startNode match {
      case Some(node) =>
        val rootNode = getRepresentativeOfSet(node.elem)
        compressedPaths += (elem -> rootNode.elem)
        Some(rootNode.elem)
      case None => None
    }
  }

  lazy val numberOfDisjointSets = nodes.values.count(_.parent == None)

  lazy val size = numberOfDisjointSets

  def canEqual(other: Any) : Boolean = {
    other.isInstanceOf[scala.logic.disjoint.DisjointSets[T]]
  }

  override def equals(other: Any) : Boolean = {
    other match {
      case that: scala.logic.disjoint.DisjointSets[T] => that.canEqual(DisjointSets.this) && nodes == that.nodes
      case _ => false // covered, but not detected by scct due to a bug :(
    }
  }

  override def hashCode() : Int = {
    val prime = 41
    prime + nodes.hashCode
  }
}

object DisjointSets {
  def apply[T](initialElements : Seq[T] = Nil) : DisjointSets[T] = new DisjointSets[T](
      initialElements.map(e => e -> Node(e, 0, None)).toMap)
}


text:
functor
=======

```
func·tor /ˈfəNG(k)tər/ noun

LOGIC MATHEMATICS
  a function; an operator.

LINGUISTICS
  another term for function word.
```

----------------------------------------------------------------------

This is WIP, get updates on twitter:

https://twitter.com/functorio

or on our website:

http://functor.io


text:
namespace {

HBITMAP GetNativeBitmapFromSkBitmap(const SkBitmap& bitmap) {
  int width = bitmap.width();
  int height = bitmap.height();

  BITMAPV4HEADER native_bitmap_header;
  gfx::CreateBitmapV4Header(width, height, &native_bitmap_header);

  HDC dc = ::GetDC(NULL);
  void* bits;
  HBITMAP native_bitmap = ::CreateDIBSection(dc,
      reinterpret_cast<BITMAPINFO*>(&native_bitmap_header),
      DIB_RGB_COLORS,
      &bits,
      NULL,
      0);
  DCHECK(native_bitmap);
  ::ReleaseDC(NULL, dc);
  bitmap.copyPixelsTo(bits, width * height * 4, width * 4);
  return native_bitmap;
}

void EnableCustomThumbnail(HWND hwnd, bool enable) {
  BOOL enable_value = enable;
  ::DwmSetWindowAttribute(hwnd,
                          DWMWA_FORCE_ICONIC_REPRESENTATION,
                          &enable_value,
                          sizeof(enable_value));
  ::DwmSetWindowAttribute(hwnd,
                          DWMWA_HAS_ICONIC_BITMAP,
                          &enable_value,
                          sizeof(enable_value));
}

}  // namespace

TaskbarWindowThumbnailerWin::TaskbarWindowThumbnailerWin(
    HWND hwnd, TaskbarWindowThumbnailerDelegateWin* delegate)
    : hwnd_(hwnd),
      delegate_(delegate) {
  ui::HWNDSubclass::AddFilterToTarget(hwnd_, this);
}

TaskbarWindowThumbnailerWin::~TaskbarWindowThumbnailerWin() {
  ui::HWNDSubclass::RemoveFilterFromAllTargets(this);
}

void TaskbarWindowThumbnailerWin::Start() {
  EnableCustomThumbnail(hwnd_, true);
}

void TaskbarWindowThumbnailerWin::Stop() {
  capture_bitmap_.reset();
  EnableCustomThumbnail(hwnd_, false);
}

void TaskbarWindowThumbnailerWin::CaptureSnapshot() {
  if (!capture_bitmap_)
    capture_bitmap_.reset(CaptureWindowImage());
}

void TaskbarWindowThumbnailerWin::InvalidateSnapshot() {
  capture_bitmap_.reset();

  // The snapshot feeded to the system could be cached. Invalidate it.
  ::DwmInvalidateIconicBitmaps(hwnd_);
}

void TaskbarWindowThumbnailerWin::ReplaceWindow(HWND new_hwnd) {
  // Stop serving the custom thumbnail for the old window.
  EnableCustomThumbnail(hwnd_, false);
  ui::HWNDSubclass::RemoveFilterFromAllTargets(this);

  hwnd_ = new_hwnd;

  // Start serving the custom thumbnail to the new window.
  ui::HWNDSubclass::AddFilterToTarget(hwnd_, this);
  EnableCustomThumbnail(hwnd_, true);
}

bool TaskbarWindowThumbnailerWin::FilterMessage(HWND hwnd,
                                                UINT message,
                                                WPARAM w_param,
                                                LPARAM l_param,
                                                LRESULT* l_result) {
  DCHECK_EQ(hwnd_, hwnd);
  switch (message) {
    case WM_DWMSENDICONICTHUMBNAIL:
      return OnDwmSendIconicThumbnail(HIWORD(l_param),
                                      LOWORD(l_param),
                                      l_result);
    case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
      return OnDwmSendIconicLivePreviewBitmap(l_result);
  }
  return false;
}

bool TaskbarWindowThumbnailerWin::OnDwmSendIconicThumbnail(
    int width, int height, LRESULT* l_result) {
  CaptureSnapshot();

  SkBitmap* thumbnail_bitmap = capture_bitmap_.get();

  // Scale the image if needed.
  SkBitmap scaled_bitmap;
  if (capture_bitmap_->width() != width ||
      capture_bitmap_->height() != height) {
    double x_scale = static_cast<double>(width) / capture_bitmap_->width();
    double y_scale = static_cast<double>(height) / capture_bitmap_->height();
    double scale = std::min(x_scale, y_scale);
    width = capture_bitmap_->width() * scale;
    height = capture_bitmap_->height() * scale;
    scaled_bitmap = skia::ImageOperations::Resize(
        *capture_bitmap_, skia::ImageOperations::RESIZE_GOOD, width, height);
    thumbnail_bitmap = &scaled_bitmap;
  }

  HBITMAP native_bitmap = GetNativeBitmapFromSkBitmap(*thumbnail_bitmap);
  ::DwmSetIconicThumbnail(hwnd_, native_bitmap, 0);
  ::DeleteObject(native_bitmap);

  *l_result = 0;
  return true;
}

bool TaskbarWindowThumbnailerWin::OnDwmSendIconicLivePreviewBitmap(
    LRESULT* l_result) {
  CaptureSnapshot();

  HBITMAP native_bitmap = GetNativeBitmapFromSkBitmap(*capture_bitmap_);
  ::DwmSetIconicLivePreviewBitmap(hwnd_, native_bitmap, NULL, 0);
  ::DeleteObject(native_bitmap);
  *l_result = 0;
  return true;
}

SkBitmap* TaskbarWindowThumbnailerWin::CaptureWindowImage() const {
  std::vector<HWND> snapshot_hwnds;
  if (delegate_)
    snapshot_hwnds = delegate_->GetSnapshotWindowHandles();
  if (snapshot_hwnds.empty())
    snapshot_hwnds.push_back(hwnd_);

  int enclosing_x = 0;
  int enclosing_y = 0;
  int enclosing_right = 0;
  int enclosing_bottom = 0;
  for (std::vector<HWND>::const_iterator iter = snapshot_hwnds.begin();
       iter != snapshot_hwnds.end(); ++iter) {
    RECT bounds;
    if (!::GetWindowRect(*iter, &bounds))
      continue;
    if (iter == snapshot_hwnds.begin()) {
      enclosing_x = bounds.left;
      enclosing_y = bounds.top;
      enclosing_right = bounds.right;
      enclosing_bottom = bounds.bottom;
    } else {
      if (bounds.left < enclosing_x)
        enclosing_x = bounds.left;
      if (bounds.top < enclosing_y)
        enclosing_y = bounds.top;
      if (bounds.right > enclosing_right)
        enclosing_right = bounds.right;
      if (bounds.bottom > enclosing_bottom)
        enclosing_bottom = bounds.bottom;
    }
  }

  int width = enclosing_right - enclosing_x;
  int height = enclosing_bottom - enclosing_y;
  if (!width || !height)
    return NULL;

  gfx::Canvas canvas(gfx::Size(width, height), ui::SCALE_FACTOR_100P, false);
  {
    skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
    HDC target_dc = scoped_platform_paint.GetPlatformSurface();
    for (std::vector<HWND>::const_iterator iter = snapshot_hwnds.begin();
         iter != snapshot_hwnds.end(); ++iter) {
      HWND current_hwnd = *iter;
      RECT current_bounds;
      if (!::GetWindowRect(current_hwnd, &current_bounds))
        continue;
      base::win::ScopedGetDC source_dc(current_hwnd);
      ::BitBlt(target_dc,
               current_bounds.left - enclosing_x,
               current_bounds.top - enclosing_y,
               current_bounds.right - current_bounds.left,
               current_bounds.bottom - current_bounds.top,
               source_dc,
               0,
               0,
               SRCCOPY);
      ::ReleaseDC(current_hwnd, source_dc);
    }
  }
  return new SkBitmap(canvas.ExtractImageRep().sk_bitmap());
}


text:
import discord
import feedparser
import in_place
import os
import re
import pprint
import readline
import shutil
import sys

from configparser import ConfigParser

# Get login_token from config:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
HOME_DIR = os.path.expanduser("~")

AUTH_CONFIG_PATHS = [
    os.path.join(HOME_DIR, ".feed2discord.auth.ini"),
    os.path.join(BASE_DIR, "feed2discord.auth.ini"),
    os.path.join("feed2discord.auth.ini"),
    os.path.join(HOME_DIR, ".feed2discord.ini"),
    os.path.join(BASE_DIR, "feed2discord.local.ini"),
    os.path.join("feed2discord.local.ini"),
    os.path.join("/etc/feed2discord.ini"),
    os.path.join(BASE_DIR, "feed2discord.ini"),
    os.path.join("feed2discord.ini"),
]
config = ConfigParser()
config_paths = []

for path in AUTH_CONFIG_PATHS:
    if os.path.isfile(path):
        config_paths.append(path)
        break
else:
    print("No configuration file found.")
    exit()

config.read(config_paths)

login_token = config.get("MAIN", "login_token")
default_room = config.getint("MAIN", "default_room")

# Get terminal width
term_size = shutil.get_terminal_size(fallback=(80, 24))
columns = term_size[0]

# Get feed URL from CLI or prompt for it:
feed_url = ''
if len(sys.argv) == 2:
    feed_url = sys.argv[1]
else:
    feed_url = input("Feed URL: ")

feed_data = feedparser.parse(feed_url)
pp = pprint.PrettyPrinter(indent=4, depth=1, width=columns)
print("Latest feed item to help you figure out fields")
print("----------")
pp.pprint(feed_data.entries[0])
print("----------")
print("Recommend: try posting links in a room somewhere to see if discord gives a nice preview")
print("----------")
print()
print("Example (if discord has nice link preview): link")
print("Example (super-typical): **title**,*published*,<link>,summary")
print("Example (super-typical): **title**,*published*,<link>,description")
print('Example (if title not great): "**Discord Status**",**title**,published,summary,<link>')
print("Example (podcast): **title**,**subtitle**,*pubDate*,link,itunes_duration")
fields = input("Feed Fields: ")

name = input("Feed and Channel Name: ")

class MyClient(discord.Client):
    room_id = 0

    async def on_ready(self):
        print('Connected!')
        print('Username: {0.name}\nID: {0.id}'.format(self.user))

        old_room = self.get_channel(default_room)
        new_room = await old_room.clone(name=name, reason=f'feedbot {feed_url} {fields}')
        await new_room.edit(reason="Update topic", topic=feed_url)
        self.room_id = new_room.id

        await self.close()

client = MyClient()
client.run(login_token)

room_id = client.room_id

room_slug = f'{name} = {room_id}'

feed_slug = f"""[{name}]
channels = {name}
feed_url = {feed_url}
fields = {fields}"""

print(room_slug)
print(feed_slug)

print("Do those look good?")
yesno = input("y/n: ")

if yesno == "y" or yesno == "Y":
    with in_place.InPlace('feed2discord.local.ini', backup_ext='~') as inifile:
        for line in inifile:
            if re.match(f'default *= *{default_room}', line):
                inifile.write(room_slug)
                inifile.write("\n")
            inifile.write(line)
        inifile.write("\n")
        inifile.write(feed_slug)
        inifile.write("\n\n")
    print("Done!")
    print("Restart feedbot to activate")
else:
    print("Not editing configuration; you probably need to cleanup a room")


text:
package org.tyrannyofheaven.bukkit.zPermissions;

import static org.tyrannyofheaven.bukkit.util.ToHLoggingUtils.debug;
import static org.tyrannyofheaven.bukkit.util.ToHLoggingUtils.error;
import static org.tyrannyofheaven.bukkit.util.ToHLoggingUtils.log;
import static org.tyrannyofheaven.bukkit.util.ToHLoggingUtils.warn;
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.broadcastAdmin;
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.colorize;
import static org.tyrannyofheaven.bukkit.util.ToHMessageUtils.sendMessage;
import static org.tyrannyofheaven.bukkit.util.ToHStringUtils.hasText;
import static org.tyrannyofheaven.bukkit.util.command.reader.CommandReader.abortBatchProcessing;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

import net.kaikk.mc.uuidprovider.UUIDProvider;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.tyrannyofheaven.bukkit.util.ToHDatabaseUtils;
import org.tyrannyofheaven.bukkit.util.ToHFileUtils;
import org.tyrannyofheaven.bukkit.util.ToHNamingConvention;
import org.tyrannyofheaven.bukkit.util.ToHSchemaVersion;
import org.tyrannyofheaven.bukkit.util.ToHStringUtils;
import org.tyrannyofheaven.bukkit.util.ToHUtils;
import org.tyrannyofheaven.bukkit.util.VersionInfo;
import org.tyrannyofheaven.bukkit.util.command.CommandExceptionHandler;
import org.tyrannyofheaven.bukkit.util.command.ToHCommandExecutor;
import org.tyrannyofheaven.bukkit.util.transaction.TransactionCallback;
import org.tyrannyofheaven.bukkit.util.transaction.TransactionCallbackWithoutResult;
import org.tyrannyofheaven.bukkit.util.transaction.TransactionStrategy;
import org.tyrannyofheaven.bukkit.util.uuid.CascadingUuidResolver;
import org.tyrannyofheaven.bukkit.util.uuid.CommandUuidResolver;
import org.tyrannyofheaven.bukkit.util.uuid.MojangUuidResolver;
import org.tyrannyofheaven.bukkit.util.uuid.UuidResolver;
import org.tyrannyofheaven.bukkit.zPermissions.PermissionsResolver.ResolverResult;
import org.tyrannyofheaven.bukkit.zPermissions.command.DirTypeCompleter;
import org.tyrannyofheaven.bukkit.zPermissions.command.GroupTypeCompleter;
import org.tyrannyofheaven.bukkit.zPermissions.command.RootCommands;
import org.tyrannyofheaven.bukkit.zPermissions.command.TrackTypeCompleter;
import org.tyrannyofheaven.bukkit.zPermissions.dao.MissingGroupException;
import org.tyrannyofheaven.bukkit.zPermissions.dao.PermissionService;
import org.tyrannyofheaven.bukkit.zPermissions.listener.ZPermissionsFallbackListener;
import org.tyrannyofheaven.bukkit.zPermissions.listener.ZPermissionsPlayerListener;
import org.tyrannyofheaven.bukkit.zPermissions.listener.ZPermissionsRegionPlayerListener;
import org.tyrannyofheaven.bukkit.zPermissions.model.DataVersion;
import org.tyrannyofheaven.bukkit.zPermissions.model.EntityMetadata;
import org.tyrannyofheaven.bukkit.zPermissions.model.Entry;
import org.tyrannyofheaven.bukkit.zPermissions.model.Inheritance;
import org.tyrannyofheaven.bukkit.zPermissions.model.Membership;
import org.tyrannyofheaven.bukkit.zPermissions.model.PermissionEntity;
import org.tyrannyofheaven.bukkit.zPermissions.model.PermissionRegion;
import org.tyrannyofheaven.bukkit.zPermissions.model.PermissionWorld;
import org.tyrannyofheaven.bukkit.zPermissions.model.UuidDisplayNameCache;
//import org.tyrannyofheaven.bukkit.zPermissions.region.FactionsRegionStrategy;
//import org.tyrannyofheaven.bukkit.zPermissions.region.FactoidRegionStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.region.RegionStrategy;
//import org.tyrannyofheaven.bukkit.zPermissions.region.ResidenceRegionStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.region.WorldGuardRegionStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.service.DefaultPlayerPrefixHandler;
import org.tyrannyofheaven.bukkit.zPermissions.service.PlayerPrefixHandler;
import org.tyrannyofheaven.bukkit.zPermissions.service.ZPermissionsServiceImpl;
import org.tyrannyofheaven.bukkit.zPermissions.storage.AvajeStorageStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.storage.FileStorageStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.storage.StorageStrategy;
import org.tyrannyofheaven.bukkit.zPermissions.util.ExpirationRefreshHandler;
import org.tyrannyofheaven.bukkit.zPermissions.util.ModelDumper;
import org.tyrannyofheaven.bukkit.zPermissions.util.RefreshTask;
import org.tyrannyofheaven.bukkit.zPermissions.uuid.AvajeBulkUuidConverter;
import org.tyrannyofheaven.bukkit.zPermissions.uuid.UUIDProvResolver;
import org.tyrannyofheaven.bukkit.zPermissions.uuid.YamlBulkUuidConverter;
import org.tyrannyofheaven.bukkit.zPermissions.vault.VaultChatBridge;
import org.tyrannyofheaven.bukkit.zPermissions.vault.VaultPermissionBridge;

import com.avaje.ebean.EbeanServer;
import com.avaje.ebeaninternal.api.SpiEbeanServer;

/**
 * zPermissions main class.
 *
 * @author zerothangel
 */
public class ZPermissionsPlugin extends JavaPlugin implements ZPermissionsCore, ZPermissionsConfig, CommandExceptionHandler {

    // Name of the default group, in absence of a config file
    private static final String DEFAULT_GROUP = "default";

    // Name of the default track, in absence of a config file
    private static final String DEFAULT_TRACK = "default";

    // Default dump directory
    private static final String DEFAULT_DUMP_DIRECTORY = "zPermissions-dumps";

    // Default timeout for temporary permissions
    private static final int DEFAULT_TEMP_PERMISSION_TIMEOUT = 60;

    // Default value for kick-on-error
    private static final boolean DEFAULT_KICK_ON_ERROR = true;

    // Default value for kick-ops-on-error
    private static final boolean DEFAULT_KICK_OPS_ON_ERROR = false;

    // Default value for region-support
    private static final boolean DEFAULT_REGION_SUPPORT_ENABLE = true;

    // Default value for assigned-groups-can-include-default
    private static final boolean DEFAULT_ASSIGNED_GROUPS_CAN_INCLUDE_DEFAULT = true;

    // Default max attempts (after the first) to complete a transaction
    private static final int DEFAULT_TXN_MAX_RETRIES = 1;

    // Default database support
    private static final boolean DEFAULT_DATABASE_SUPPORT = true;

    // Default number of ticks to wait between permissions refreshes of all players
    private static final int DEFAULT_BULK_REFRESH_DELAY = 5;

    // Default opaque inheritance
    private static final boolean DEFAULT_OPAQUE_INHERITANCE = true;

    // Default interleaved player permissions (to be changed at some future version)
    private static final boolean DEFAULT_INTERLEAVED_PLAYER_PERMISSIONS = true;

    // Default rank broadcast to admins
    private static final boolean DEFAULT_RANK_ADMIN_BROADCAST = false;

    // Default auto-refresh interval
    private static final int DEFAULT_AUTO_REFRESH_INTERVAL = -1;

    // Default auto-refresh forced refreshes
    private static final boolean DEFAULT_AUTO_REFRESH_FORCE = false;

    // Default primary group track
    private static final String DEFAULT_PRIMARY_GROUP_TRACK = null;

    // Default native Vault bridges
    private static final boolean DEFAULT_NATIVE_VAULT_BRIDGES = true;

    // Default Vault player prefix group fallback
    private static final boolean DEFAULT_VAULT_PREFIX_INCLUDES_GROUP = true;

    // Default Vault player metadata group fallback
    private static final boolean DEFAULT_VAULT_METADATA_INCLUDES_GROUP = true;

    // Default Vault behavior for playerInGroup()
    private static final boolean DEFAULT_VAULT_GROUP_TEST_USES_ASSIGNED_ONLY = false;

    // Default Vault behavior for getPlayerGroups()
    private static final boolean DEFAULT_VAULT_GET_GROUPS_USES_ASSIGNED_ONLY = false;

    // Default logging for Vault changes
    private static final boolean DEFAULT_LOG_VAULT_CHANGES = false;

    // Filename of file-based storage
    private static final String FILE_STORAGE_FILENAME = "data.yml";

    // Name of metadata key for our PlayerState instances
    private static final String PLAYER_METADATA_KEY = "zPermissions.PlayerState";

    // Default read-only flag
    private static final boolean DEFAULT_DATABASE_READ_ONLY = false;

    // Default metadata inheritance
    private static final boolean DEFAULT_INHERITED_METADATA = false;

    // Prefix for each player's dynamic permission
    public static final String DYNAMIC_PERMISSION_PREFIX = "zPermissions_player.";

    // Initial delay after initialization failure (ms)
    private static final int STARTING_INITIALIZATION_RETRY_DELAY = 30 * 1000;

    // Maximum delay after initialization failure (ms)
    private static final int MAX_INITIALIZATION_RETRY_DELAY = 8 * 60 * 1000;

    // Search batch size
    private static final int DEFAULT_SEARCH_BATCH_SIZE = 1;

    // Search delay in ticks
    private static final int DEFAULT_SEARCH_DELAY = 5;

    // Whether or not to attempt UUID migration
    private static final boolean DEFAULT_UUID_MIGRATE = true;

    // Size of UUID resolver cache
    private static final int DEFAULT_UUID_CACHE_SIZE = 1000;

    // TTL of UUID resolver cache
    private static final long DEFAULT_UUID_CACHE_TTL = 120L;

    // Whether ZPermissionService#getPlayerMetadata() should be aware of prefix/suffix
    private static final boolean DEFAULT_SERVICE_METADATA_PREFIX_HACK = false;

    // Whether default group membership should be made explicit
    private static final boolean DEFAULT_EXPLICIT_DEFAULT_GROUP_MEMBERSHIP = false;

    // Version info (may include build number)
    private VersionInfo versionInfo;

    // Permission resolver
    private PermissionsResolver resolver = new PermissionsResolver(this);

    // Model dumper
    private ModelDumper modelDumper;

    // Multi-user refreshing
    private final RefreshTask refreshTask = new RefreshTask(getZPermissionsCore(), this);

    // Our own Configuration (don't bother with JavaPlugin's)
    private FileConfiguration config;

    // The configured default track
    private String defaultTrack;

    // The configured dump directory
    private File dumpDirectory;

    // The configured default temporary permission timeout
    private int defaultTempPermissionTimeout;

    // Whether to kick users if there's any problem determining permissions
    private boolean kickOnError = DEFAULT_KICK_ON_ERROR;

    // If kickOnError is true, whether or not to kick operators too
    private boolean kickOpsOnError = DEFAULT_KICK_OPS_ON_ERROR;

    // If WorldGuard is present and this is true, enable region support
    private boolean regionSupportEnable;

    // Track definitions
    private final Map<String, List<String>> tracks = new LinkedHashMap<>();

    // Names of tracks (in original case)
    private final Set<String> trackNames = new LinkedHashSet<>();

    // Whether or not to use the database (Avaje) storage strategy
    private boolean databaseSupport;

    // Maximum number of times to retry transactions (so total attempts is +1)
    private int txnMaxRetries;

    // Interval for auto-refresh
    private int autoRefreshInterval;

    // Whether or not auto-refreshes should be forced refreshes
    private boolean autoRefreshForce;

    // Task ID for auto-refresh task
    private int autoRefreshTaskId = -1;

    // Default primary group track
    private String defaultPrimaryGroupTrack;

    // Whether to use native Vault bridges
    private boolean nativeVaultBridges;

    // Whether the native Vault bridge's getPlayerPrefix/getPlayerSuffix should
    // fall back to the primary group
    private boolean vaultPrefixIncludesGroup;

    // Wehther the native Vault bridge's getPlayerInfo* methods should
    // fall back to the primary group
    private boolean vaultMetadataIncludesGroup;

    // Whether Vault playerInGroup() should use assigned groups only
    private boolean vaultGroupTestUsesAssignedOnly;

    // Whether Vault getPlayerGroups() should use assigned groups only
    private boolean vaultGetGroupsUsesAssignedOnly;

    // Custom player prefix format
    private String vaultPlayerPrefixFormat;

    // Custom player suffix format
    private String vaultPlayerSuffixFormat;

    // Whether to log Vault changes at INFO level
    private boolean logVaultChanges;

    // Whether the database should be read-only
    private boolean databaseReadOnly;

    // Strategy for permissions storage
    private StorageStrategy storageStrategy;

    // Create our own instance rather than use Bukkit's
    private EbeanServer ebeanServer;

    // Custom NamingConvention for Avaje
    private final ToHNamingConvention namingConvention = new ToHNamingConvention(this, "zperms_schema_version");

    // Backwards compatibility. Broadcast to admins if true, the custom permissions otherwise.
    private boolean rankAdminBroadcast = DEFAULT_RANK_ADMIN_BROADCAST;

    // Handles async refreshes when memberships expire
    private ExpirationRefreshHandler expirationRefreshHandler;

    // Strategy for region detection
    private RegionStrategy regionStrategy;

    // Region managers to use in preference order
    private List<String> regionManagers;

    // Manager for metadata
    private MetadataManager metadataManager;

    // Whether metadata should follow group inheritance rules
    private boolean inheritedMetadata;

    // Search batch size
    private int searchBatchSize;

    // Search delay
    private int searchDelay;

    // Size of UUID resolver cache
    private int uuidResolverCacheSize;

    // TTL of UUID resolver cache
    private long uuidResolverCacheTtl;

    // UUID resolver service
    private UuidResolver uuidResolver;

    // Whether or not to attempt UUID migration
    private boolean uuidMigrate;

    // Async Executor for CommandUuidResolver
    private ExecutorService commandUuidResolverExecutor;

    // Whether ZPermissionService#getPlayerMetadata() should be aware of prefix/suffix
    private boolean serviceMetadataPrefixHack;

    private String storageStrategyClassName;

    // Whether default group membership should be made explicit
    private boolean explicitDefaultGroupMembership;

    //UUID Provider plugin - this is used to validate UUIDProvider to related classes
    public UUIDProvider uuidprov = null;

    /**
     * Retrieve this plugin's retrying TransactionStrategy
     * FIXME We use a separate TransactionStrategy because not all transactions
     * might be safe to be retried. Most simple transactions are safe to retry.
     * The ones that perform calculations or other operations (most notably
     * the rank commands) will have to be dealt with another way...
     *
     * @return the retrying TransactionStrategy
     */
    private TransactionStrategy getRetryingTransactionStrategy() {
        return storageStrategy.getRetryingTransactionStrategy();
    }

    /**
     * Retrieve this plugin's PermissionService.
     *
     * @return the PermissionService
     */
    PermissionService getPermissionService() {
        return storageStrategy.getPermissionService();
    }

    // Retrieve the PermissionResolver instance
    private PermissionsResolver getResolver() {
        return resolver;
    }

    // Retrieve ModelDumper instance
    private ModelDumper getModelDumper() {
        return modelDumper;
    }

    // Retrieve ZPermissionsCore instance
    private ZPermissionsCore getZPermissionsCore() {
        return this;
    }

    // Retrieve ZPermissionsConfig instance
    private ZPermissionsConfig getZPermissionsConfig() {
        return this;
    }

    @Override
    public void onLoad() {
        versionInfo = ToHUtils.getVersion(this);
    }

    /* (non-Javadoc)
     * @see org.bukkit.plugin.Plugin#onDisable()
     */
    @Override
    public void onDisable() {
        // Shutdown async UUID resolver
        if (commandUuidResolverExecutor != null) {
            commandUuidResolverExecutor.shutdownNow();
            commandUuidResolverExecutor = null;
        }

        // Shut down region manager
        if (regionStrategy != null) {
            regionStrategy.shutdown();
            regionStrategy = null;
        }

        // Kill expiration handler
        if (expirationRefreshHandler != null) {
            expirationRefreshHandler.shutdown();
            expirationRefreshHandler = null;
        }

        // Kill pending refresh, if any
        refreshTask.stop();

        // Really shut off all async tasks
        getServer().getScheduler().cancelTasks(this);

        // Ensure storage is shut down properly
        if (storageStrategy != null) {
            storageStrategy.shutdown();
            storageStrategy = null;
        }

        // Clear any player state

        // Remove permissions
        for (Player player : Bukkit.getOnlinePlayers()) {
            removeBukkitPermissions(player, true);
        }

        log(this, "%s disabled.", versionInfo.getVersionString());
    }

    /* (non-Javadoc)
     * @see org.bukkit.plugin.Plugin#onEnable()
     */
    @Override
    public void onEnable() {
        try {
            log(this, "%s starting...", versionInfo.getVersionString());

            // FIXME Defaults workaround, to be removed after 1.0
            boolean isUpgrade = new File(getDataFolder(), "config.yml").exists();
            // FIXME Defaults workaround end

            // Read config
            config = ToHFileUtils.getConfig(this);
            config.options().header(null);
            // FIXME Defaults workaround, to be removed after 1.0
            if (!isUpgrade)
                config.set("interleaved-player-permissions", false);
            // FIXME Defaults workaround end
            readConfig();

            // Upgrade/create config
            ToHFileUtils.upgradeConfig(this, config);
        }
        catch (Throwable t) {
            unrecoverableError("config", t);
            if (t instanceof Error)
                throw (Error)t;
            return;
        }

        //Verify that UUIDProvider is running
        try {
        	Plugin uuidplugin = this.getServer().getPluginManager().getPlugin("UUIDProvider");
        	if(uuidplugin instanceof UUIDProvider){
        		this.uuidprov = (UUIDProvider)uuidplugin;
        		getLogger().info("Found UUIDProvider plugin! Using UUIDProvider for Resolving/Converting services!");
        	} else {
        		getLogger().warning("Could not find UUIDProvider - Will use default zPerms UUID Resolving/Converting services - NOT COMPATIBLE WITH 1.6.4!");
        	}
        } catch (Exception e) {
        	getLogger().severe("Caught exception establishing external UUID Provider services : ");
        	getLogger().severe(e.getMessage());
        	e.printStackTrace();
        }
        // Instantiate UUID resolver service
        if(uuidprov != null){
        	//Use UUIDProvider Resolver, instead of the mojang resolver.
        	uuidResolver = new UUIDProvResolver(this);
        } else {
        	//Just use the mojang resolver - will be OK on 1.7.10.
        	uuidResolver = new MojangUuidResolver(uuidResolverCacheSize, uuidResolverCacheTtl, TimeUnit.MINUTES);
        }
        // Attempt to initialize storage, retrying indefinitely (with exponential backoff)
        int initializationRetryDelay = STARTING_INITIALIZATION_RETRY_DELAY;

        while (!initializeStorageStrategy()) {
            error(this, "Will retry after %d seconds...", initializationRetryDelay / 1000);
            error(this, "(You may CTRL-C to stop the server)");
            try {
                Thread.sleep(initializationRetryDelay);
            }
            catch (InterruptedException e) {
                // Just get outta here
                // Not sure if this is ever reached. But just to be safe...
                Bukkit.getServer().shutdown();
                return;
            }

            // Increase retry delay
            initializationRetryDelay = Math.min(2 * initializationRetryDelay, MAX_INITIALIZATION_RETRY_DELAY);
        }

        initializeEverythingElse();
    }

    private void unrecoverableError(String module, Throwable t) {
        error(this, "Failed to initialize (%s): ", module, t);
        if (kickOnError) {
            error(this, "ALL %sLOG-INS DISALLOWED", kickOpsOnError ? "" : "NON-OP ");
            Bukkit.getPluginManager().registerEvents(new ZPermissionsFallbackListener(kickOpsOnError), this);
        }
        error(this, "THIS IS NON-RECOVERABLE. You must /reload or restart to try again.");
    }

    private boolean initializeStorageStrategy() {
        try {
            // Set up TransactionStrategy and PermissionService
            storageStrategy = null;

            if (hasText(storageStrategyClassName)) {
                // Use a custom StorageStrategy implementation
                log(this, "Using custom storage strategy: %s", storageStrategyClassName);
                storageStrategy = (StorageStrategy)Class.forName(storageStrategyClassName).newInstance();
            }
            else if (databaseSupport) {
                // Use the default Avaje-based StorageStrategy
                ebeanServer = ToHDatabaseUtils.createEbeanServer(this, getClassLoader(), namingConvention, config);

                SpiEbeanServer spiEbeanServer = (SpiEbeanServer)ebeanServer;
                if (spiEbeanServer.getDatabasePlatform().getName().contains("sqlite")) {
                    log(this, Level.WARNING, "This plugin is NOT compatible with SQLite.");
                    log(this, Level.WARNING, "Edit bukkit.yml to switch databases or disable database support in config.yml.");
                    log(this, Level.WARNING, "Falling back to file-based storage strategy.");
                    // Do nothing else (storageStrategy still null)
                }
                else {
                    ToHDatabaseUtils.upgradeDatabase(this, namingConvention, getClassLoader(), "sql");

                    if (uuidMigrate) {
                        // Perform migration
                        new AvajeBulkUuidConverter(this, uuidResolver).migrate();
                    }

                    log(this, "Using database storage strategy.");
                    storageStrategy = new AvajeStorageStrategy(this, txnMaxRetries, databaseReadOnly);
                }
            }

            // If still no storage strategy at this point, use flat-file one
            if (storageStrategy == null) {
                log(this, "Using file-based storage strategy.");
                File dataFile = new File(getDataFolder(), FILE_STORAGE_FILENAME);

                if (uuidMigrate) {
                    // Perform migration
                    new YamlBulkUuidConverter(this, uuidResolver, dataFile).migrate();
                }

                storageStrategy = new FileStorageStrategy(this, dataFile);
            }

            // Initialize storage strategy
            Map<String, Object> configMap = config.getValues(true);
            storageStrategy.init(configMap);

            // Set up UuidResolver cascade if StorageStrategy implementation happens
            // to also implement UuidResolver
            if (storageStrategy instanceof UuidResolver && uuidprov == null) {
            	//If we're not using UUIDProvider services, allow the cascading UUID resolver to run.
            	//This will increase efficiency on 1.7.10 servers without UUIDProvider.
                log(this, "Using storage strategy as first-level UUID resolver.");
                uuidResolver = new CascadingUuidResolver((UuidResolver)storageStrategy, uuidResolver);
            }
        }
        catch (Exception e) {
            error(this, "Failed to initialize (storage): ", e);
            return false;
        }

        return true;
    }

    // Initialization of everything else post-storage
    private void initializeEverythingElse() {
        try {
            modelDumper = new ModelDumper(storageStrategy, this);

            // Initialize player UUID resolver for commands
            commandUuidResolverExecutor = Executors.newSingleThreadExecutor();
            CommandUuidResolver commandUuidResolver = new CommandUuidResolver(this, uuidResolver, commandUuidResolverExecutor, false /* TODO true after 1.3 */);

            // Install our commands
            (new ToHCommandExecutor<ZPermissionsPlugin>(this, new RootCommands(getZPermissionsCore(), storageStrategy, getResolver(), getModelDumper(), getZPermissionsConfig(), this, commandUuidResolver, uuidResolver)))
                .registerTypeCompleter("group", new GroupTypeCompleter(getPermissionService()))
                .registerTypeCompleter("track", new TrackTypeCompleter(getZPermissionsConfig()))
                .registerTypeCompleter("dump-dir", new DirTypeCompleter(getZPermissionsConfig()))
                .setQuoteAware(true)
                .setExceptionHandler(this)
                .setVerbosePermissionErrorPermission("zpermissions.error.detail")
                .registerCommands();

            // Detect a region manager
            initializeRegionStrategy();
            boolean regionSupport = regionStrategy != null && regionSupportEnable; // Need both

            // Install our listeners
            expirationRefreshHandler = new ExpirationRefreshHandler(getZPermissionsCore(), storageStrategy, this);
            Bukkit.getPluginManager().registerEvents(new ZPermissionsPlayerListener(getZPermissionsCore(), this, uuidResolver), this);
            if (regionSupport) {
                Bukkit.getPluginManager().registerEvents(new ZPermissionsRegionPlayerListener(getZPermissionsCore()), this);
                log(this, "%s region support: %s", regionStrategy.getName(), regionStrategy.isEnabled() ? "Enabled" : "Waiting");
            }

            // Set up MetadataManager
            metadataManager = new MetadataManager(getResolver(), getRetryingTransactionStrategy());

            // Set up service API
            PlayerPrefixHandler prefixHandler = new DefaultPlayerPrefixHandler(getZPermissionsConfig());
            ZPermissionsService service = new ZPermissionsServiceImpl(this, getResolver(), getPermissionService(), metadataManager, getRetryingTransactionStrategy(), getZPermissionsConfig(), prefixHandler);
            getServer().getServicesManager().register(ZPermissionsService.class, service, this, ServicePriority.Normal);

            if (nativeVaultBridges && Bukkit.getPluginManager().getPlugin("Vault") != null) {
                // Set up Vault bridges
                new VaultPermissionBridge(this, getResolver(), storageStrategy, getZPermissionsCore(), service, getZPermissionsConfig()).register();
                log(this, "Installed native Vault Permissions bridge");
                new VaultChatBridge(this, getZPermissionsCore(), storageStrategy, service, getZPermissionsConfig()).register();
                log(this, "Installed native Vault Chat bridge");
            }

            // Make sure everyone currently online has permissions
            // NB Do in foreground
            for (Player player : Bukkit.getOnlinePlayers()) {
                refreshPlayer(UUIDProvider.retrieve(player.getName()), RefreshCause.GROUP_CHANGE);
            }

            // Start auto-refresh task, if one is configured
            startAutoRefreshTask();

            // Initialize expiration handler
            refreshExpirations();

            log(this, "%s enabled.", versionInfo.getVersionString());
        }
        catch (Throwable t) {
            unrecoverableError("everything else", t);
            if (t instanceof Error)
                throw (Error)t;
        }
    }

    private void initializeRegionStrategy() {
        regionStrategy = null;

        if (!regionSupportEnable)
            return; // Don't bother with the rest

        Map<String, RegionStrategy> strategies = new LinkedHashMap<>();
        RegionStrategy regionStrategy;

        // WorldGuard
        regionStrategy = new WorldGuardRegionStrategy(this, getZPermissionsCore());
        strategies.put(regionStrategy.getName(), regionStrategy);

        // Additional region managers are registered here.
        //regionStrategy = new ResidenceRegionStrategy(this, getZPermissionsCore());
        //strategies.put(regionStrategy.getName(), regionStrategy);

        //regionStrategy = new FactionsRegionStrategy(this, getZPermissionsCore());
        //strategies.put(regionStrategy.getName(), regionStrategy);

        //regionStrategy = new FactoidRegionStrategy(this, getZPermissionsCore());
        //strategies.put(regionStrategy.getName(), regionStrategy);

        // Run through list in preference order
        for (String rmName : regionManagers) {
            regionStrategy = strategies.get(rmName);
            if (regionStrategy == null) {
                // Misconfiguration
                warn(this, "Unknown region manager '%s'. Valid values are: %s", rmName, ToHStringUtils.delimitedString(", ", strategies.keySet()));
                continue;
            }

            if (regionStrategy.isPresent()) {
                debug(this, "Found region manager %s", regionStrategy.getName());
                regionStrategy.init();
                this.regionStrategy = regionStrategy;
                return;
            }
        }
    }

    @Override
    public EbeanServer getDatabase() {
        return ebeanServer;
    }

    /* (non-Javadoc)
     * @see org.bukkit.plugin.java.JavaPlugin#getDatabaseClasses()
     */
    @Override
    public List<Class<?>> getDatabaseClasses() {
        List<Class<?>> result = new ArrayList<>();
        result.add(ToHSchemaVersion.class);
        result.add(PermissionEntity.class);
        result.add(Inheritance.class);
        result.add(PermissionRegion.class);
        result.add(PermissionWorld.class);
        result.add(Entry.class);
        result.add(Membership.class);
        result.add(EntityMetadata.class);
        result.add(DataVersion.class);
        result.add(UuidDisplayNameCache.class);
        return result;
    }

    // Remove all state associated with a player
    @Override
    public void removeBukkitPermissions(Player player, boolean recalculate) {
        debug(this, "Removing permissions for %s", player.getName());
        // NB Attachment is recycled along with the player instance

        // Disassociate PlayerState
        player.removeMetadata(PLAYER_METADATA_KEY, this);

        // Remove dynamic permission and recalculate, if wanted
        final String permName = DYNAMIC_PERMISSION_PREFIX + UUIDProvider.retrieve(player.getName()).toString();
        Bukkit.getPluginManager().removePermission(permName);
        if (recalculate) {
            for (Permissible p : Bukkit.getPluginManager().getPermissionSubscriptions(permName)) {
                p.recalculatePermissions();
            }
        }
    }

    // Update state about a player, resolving effective permissions and
    // creating/updating their attachment
    @Override
    public void setBukkitPermissions(Player player, Location location, boolean force, RefreshCause eventCause) {
        boolean changed = false;
        try {
            changed = setBukkitPermissionsInternal(player, location, force);
        }
        catch (Error e) {
            throw e; // Never catch errors
        }
        catch (Throwable t) {
            error(this, "Exception while updating permissions for %s", player.getName(), t);
            broadcastAdmin(this, colorize("{RED}SEVERE error while determining permissions; see server.log!"));

            // Kick the player, if configured to do so
            if (kickOnError && (kickOpsOnError || !player.isOp())) {
                // Probably safer to do this synchronously
                final String playerName = player.getName();
                getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                    @Override
                    public void run() {
                        Player player = getServer().getPlayer(playerName);
                        if (player != null)
                            player.kickPlayer("Error determining your permissions");
                    }
                });
            }
            else {
                // Ensure player has no permissions
                removeBukkitPermissions(player, true);
                sendMessage(player, colorize("{RED}Error determining your permissions; all permissions removed!"));
            }
        }

        // Fire off event if requested and changed
        if (eventCause != null && changed) {
            final String playerName = player.getName();
            // Translate RefreshEvent to ZPermissionsPlayerPermissionsChangeEvent.Cause
            // Kinda dumb, but I don't want internal code to depend on the event class.
            final ZPermissionsPlayerUpdateEvent.Cause cause;
            switch (eventCause) {
            case COMMAND:
                cause = ZPermissionsPlayerUpdateEvent.Cause.COMMAND;
                break;
            case GROUP_CHANGE:
                cause = ZPermissionsPlayerUpdateEvent.Cause.GROUP_CHANGE;
                break;
            case MOVEMENT:
                cause = ZPermissionsPlayerUpdateEvent.Cause.MOVEMENT;
                break;
            default:
                throw new AssertionError("Unhandled RefreshCause: " + eventCause);
            }
            // Fire it off on the following tick
            Bukkit.getScheduler().runTask(this, new Runnable() {
                @Override
                public void run() {
                    Player player = Bukkit.getPlayer(playerName);
                    if (player != null) {
                        ZPermissionsPlayerUpdateEvent event = new ZPermissionsPlayerUpdateEvent(player, cause);
                        Bukkit.getPluginManager().callEvent(event);
                    }
                }
            });
        }
    }

    // Simulate failures probabilistically
//    private final java.util.Random failureChance = new java.util.Random();
//    private void fakeFailureChance() {
//        if (failureChance.nextDouble() < 0.2)
//            throw new RuntimeException("Oh noes! An error!");
//    }

    // Update state about a player, resolving effective permissions and
    // creating/updating their attachment
    private boolean setBukkitPermissionsInternal(final Player player, Location location, boolean force) {
        final Set<String> regions = getRegions(location, player);

        // Fetch existing state
        final String permName = DYNAMIC_PERMISSION_PREFIX + UUIDProvider.retrieve(player.getName()).toString();
        Permission perm = Bukkit.getPluginManager().getPermission(permName);

        PlayerState playerState = getPlayerState(player);

        boolean hasPermissionAttachment = player.isPermissionSet(permName) && player.hasPermission(permName);

        // Check if the player is missing any state or changed worlds/regions
        if (!force) {
            force = perm == null ||
                    playerState == null ||
                    !hasPermissionAttachment ||
                    !regions.equals(playerState.getRegions()) ||
                    !location.getWorld().getName().equals(playerState.getWorld());
        }

        // No need to update yet (most likely called by movement-based event)
        if (!force) return false;

        debug(this, "Updating permissions for %s", player.getName());
        debug(this, "  location = %s", location);
        debug(this, "  regions = %s", regions);

        // Resolve effective permissions
        final String world = location.getWorld().getName().toLowerCase();
        ResolverResult resolverResult = getRetryingTransactionStrategy().execute(new TransactionCallback<ResolverResult>() {
            @Override
            public ResolverResult doInTransaction() throws Exception {
//                fakeFailureChance();
                return getResolver().resolvePlayer(UUIDProvider.retrieve(player.getName()), world, regions);
            }
        }, true);

        debug(this, "(Existing Permission: %s, PlayerState: %s, PermissionAttachment: %s)", perm != null, playerState != null, hasPermissionAttachment);

        // Create dynamic permission to hold all permissions this player should have at this moment
        if (perm == null) {
            // NB This implicitly calls recalculatePermissibles(). However, since it has not been
            // added yet, permissibles will not pick up its children.
            perm = new Permission(permName, PermissionDefault.FALSE, resolverResult.getPermissions());
            Bukkit.getPluginManager().addPermission(perm);
        }
        else {
            perm.getChildren().clear();
            perm.getChildren().putAll(resolverResult.getPermissions());
        }
        // If player already has an attachment, then it will recalculate here.
        // Otherwise subscribers will be empty and nothing really happens. The
        // recalculation will then occur when the attachment is added below.
        perm.recalculatePermissibles();

        if (playerState != null) {
            // Update values
            playerState.setRegions(regions);
            playerState.setWorld(location.getWorld().getName());
            playerState.setGroups(resolverResult.getGroups());
        }
        else {
            // Create brand new PlayerState
            playerState = new PlayerState(regions, location.getWorld().getName(), resolverResult.getGroups());
            player.setMetadata(PLAYER_METADATA_KEY, new FixedMetadataValue(this, playerState));
        }

        // Finally, create attachment if missing
        if (!hasPermissionAttachment) {
            player.addAttachment(this, perm.getName(), true);
        }

        return true;
    }

    /**
     * Returns names of regions that contain the location
     *
     * @param location the location
     * @param player the player in question (for supplemental info)
     * @return set of region names containing location
     */
    public Set<String> getRegions(Location location, Player player) {
        if (regionSupportEnable && regionStrategy != null && regionStrategy.isEnabled()) {
            return regionStrategy.getRegions(location, player);
        }
        return Collections.emptySet();
    }

    /**
     * Refresh a particular player's attachment (and therefore, effective
     * permissions). Only does something if the player is actually online.
     *
     * @param uuid the UUID of the player
     * @param cause the cause of this refresh
     */
    @Override
    public void refreshPlayer(UUID uuid, RefreshCause cause) {
        Player player = Bukkit.getPlayer(UUIDProvider.retrieve(uuid));
        if (player != null) {
            debug(this, "Refreshing player %s", player.getName());
            setBukkitPermissions(player, player.getLocation(), true, cause);
        }
    }

    /**
     * Refresh the attachments of all online players.
     */
    @Override
    public void refreshPlayers() {
        debug(this, "Refreshing all online players");
        Set<UUID> toRefresh = new HashSet<>();
        for (Player player : Bukkit.getOnlinePlayers()) {
            toRefresh.add(UUIDProvider.retrieve(player.getName()));
        }
        refreshTask.start(toRefresh);
    }

    /**
     * Refresh the attachments of a specific set of players.
     *
     * @param playerUuids collection of players to refresh
     */
    @Override
    public void refreshPlayers(Collection<UUID> playerUuids) {
        refreshTask.start(playerUuids);
    }

    /**
     * Refresh expiration task.
     */
    @Override
    public void refreshExpirations() {
        expirationRefreshHandler.rescan();
    }

    /**
     * Refresh expiration task if the given player is online.
     *
     * @param uuid the UUID of the player
     */
    @Override
    public void refreshExpirations(UUID uuid) {
        if (Bukkit.getPlayer(UUIDProvider.retrieve(uuid)) != null)
            refreshExpirations();
    }

    /**
     * Refresh all players who are members of the given group.
     *
     * @param groupName the affected group
     */
    @Override
    public boolean refreshAffectedPlayers(String groupName) {
        groupName = groupName.toLowerCase();
        Set<UUID> toRefresh = new HashSet<>();
        for (Player player : Bukkit.getOnlinePlayers()) {
            PlayerState playerState = getPlayerState(player);
            if (playerState == null || playerState.getGroups().contains(groupName)) {
                toRefresh.add(UUIDProvider.retrieve(player.getName()));
            }
        }

        if (toRefresh.isEmpty())
            return false; // Nothing to do

        if (getLogger().isLoggable(Level.CONFIG))
            debug(this, "Refreshing players: %s", ToHStringUtils.delimitedString(", ", toRefresh));
        refreshTask.start(toRefresh);

        return true;
    }

    /**
     * Retrieve the configured default track.
     *
     * @return the default track
     */
    @Override
    public String getDefaultTrack() {
        return defaultTrack;
    }

    /**
     * Retrieve the list of groups for the given track.
     *
     * @param trackName the name of the track
     * @return a list of groups (in ascending order) associated with the track
     */
    @Override
    public List<String> getTrack(String trackName) {
        return tracks.get(trackName.toLowerCase());
    }

    /**
     * Retrieve names of all tracks.
     *
     * @return names of all tracks
     */
    @Override
    public List<String> getTracks() {
        return new ArrayList<>(trackNames);
    }

    /**
     * Returns the configured dump directory.
     *
     * @return the dump directory
     */
    @Override
    public File getDumpDirectory() {
        return dumpDirectory;
    }

    /**
     * Returns the configured default temporary permission timeout.
     *
     * @return the temp permission timeout in seconds
     */
    @Override
    public int getDefaultTempPermissionTimeout() {
        return defaultTempPermissionTimeout;
    }

    /**
     * Returns the configured value for rank-admin-broadcast.
     *
     * @return whether to broadcast rank changes to admins
     */
    @Override
    public boolean isRankAdminBroadcast() {
        return rankAdminBroadcast;
    }

    /**
     * Returns the default track used to determine the primary group.
     *
     * @return the default primary group track
     */
    @Override
    public String getDefaultPrimaryGroupTrack() {
        return defaultPrimaryGroupTrack;
    }

    @Override
    public boolean isVaultPrefixIncludesGroup() {
        return vaultPrefixIncludesGroup;
    }

    @Override
    public boolean isVaultMetadataIncludesGroup() {
        return vaultMetadataIncludesGroup;
    }

    @Override
    public boolean isVaultGroupTestUsesAssignedOnly() {
        return vaultGroupTestUsesAssignedOnly;
    }

    @Override
    public boolean isVaultGetGroupsUsesAssignedOnly() {
        return vaultGetGroupsUsesAssignedOnly;
    }

    public boolean isInheritedMetadata() {
        return inheritedMetadata;
    }

    public void setInheritedMetadata(boolean inheritedMetadata) {
        this.inheritedMetadata = inheritedMetadata;
    }

    // Read config.yml
    private void readConfig() {
        // Set debug logging
        getLogger().setLevel(config.getBoolean("debug", false) ? Level.CONFIG : null);

        // Barebones defaults
        databaseSupport = config.getBoolean("database-support", DEFAULT_DATABASE_SUPPORT);
        databaseReadOnly = config.getBoolean("database-read-only", DEFAULT_DATABASE_READ_ONLY);
        getResolver().setDefaultGroup(DEFAULT_GROUP);
        defaultTrack = DEFAULT_TRACK;
        dumpDirectory = new File(DEFAULT_DUMP_DIRECTORY);
        getResolver().setGroupPermissionFormats(null);
        getResolver().setAssignedGroupPermissionFormats(null);
        tracks.clear();
        trackNames.clear();
        defaultPrimaryGroupTrack = DEFAULT_PRIMARY_GROUP_TRACK;

        String value;

        // Read values, set accordingly
        Object strOrList = config.get("group-permission");
        if (strOrList != null) {
            if (strOrList instanceof String) {
                if (hasText((String)strOrList))
                    getResolver().setGroupPermissionFormats(Collections.singleton((String)strOrList));
            }
            else if (strOrList instanceof List<?>) {
                Set<String> groupPerms = new HashSet<>();
                for (Object obj : (List<?>)strOrList) {
                    if (obj instanceof String) {
                        groupPerms.add((String)obj);
                    }
                    else
                        warn(this, "group-permission list contains non-string value");
                }
                getResolver().setGroupPermissionFormats(groupPerms);
            }
            else
                warn(this, "group-permission must be a string or list of strings");
        }

        // TODO refactor
        strOrList = config.get("assigned-group-permission");
        if (strOrList != null) {
            if (strOrList instanceof String) {
                if (hasText((String)strOrList))
                    getResolver().setAssignedGroupPermissionFormats(Collections.singleton((String)strOrList));
            }
            else if (strOrList instanceof List<?>) {
                Set<String> groupPerms = new HashSet<>();
                for (Object obj : (List<?>)strOrList) {
                    if (obj instanceof String) {
                        groupPerms.add((String)obj);
                    }
                    else
                        warn(this, "assigned-group-permission list contains non-string value");
                }
                getResolver().setAssignedGroupPermissionFormats(groupPerms);
            }
            else
                warn(this, "assigned-group-permission must be a string or list of strings");
        }

        getResolver().setOpaqueInheritance(config.getBoolean("opaque-inheritance", DEFAULT_OPAQUE_INHERITANCE));
        getResolver().setInterleavedPlayerPermissions(config.getBoolean("interleaved-player-permissions", DEFAULT_INTERLEAVED_PLAYER_PERMISSIONS));
        getResolver().setIncludeDefaultInAssigned(config.getBoolean("assigned-groups-can-include-default", DEFAULT_ASSIGNED_GROUPS_CAN_INCLUDE_DEFAULT));

        value = config.getString("default-group");
        if (hasText(value))
            getResolver().setDefaultGroup(value);
        explicitDefaultGroupMembership = config.getBoolean("explicit-default-group-membership", DEFAULT_EXPLICIT_DEFAULT_GROUP_MEMBERSHIP);

        value = config.getString("default-track");
        if (hasText(value))
            defaultTrack = value;

        value = config.getString("dump-directory");
        if (hasText(value))
            dumpDirectory = new File(value);

        value = config.getString("default-primary-group-track");
        if (hasText(value))
            defaultPrimaryGroupTrack = value;

        defaultTempPermissionTimeout = config.getInt("default-temp-permission-timeout", DEFAULT_TEMP_PERMISSION_TIMEOUT);
        txnMaxRetries = config.getInt("txn-max-retries", DEFAULT_TXN_MAX_RETRIES); // FIXME hidden
        rankAdminBroadcast = config.getBoolean("rank-admin-broadcast", DEFAULT_RANK_ADMIN_BROADCAST);

        // Read tracks, if any
        ConfigurationSection node = config.getConfigurationSection("tracks");
        if (node != null) {
            for (String trackName : node.getKeys(false)) {
                List<?> list = node.getList(trackName);
                if (list == null) {
                    warn(this, "Track %s must have a list value", trackName);
                    continue;
                }

                List<String> members = new ArrayList<>();
                for (Object o : list) {
                    members.add(o.toString().toLowerCase());
                }
                tracks.put(trackName.toLowerCase(), members);
                trackNames.add(trackName);
            }
        }
        // Set up default track if none are defined
        if (tracks.isEmpty()) {
            List<String> members = new ArrayList<>();
            members.add("default");
            members.add("somegroup");
            members.add("someothergroup");
            tracks.put("default", members);
            trackNames.add("default");
        }

        kickOnError = config.getBoolean("kick-on-error", DEFAULT_KICK_ON_ERROR);
        kickOpsOnError = config.getBoolean("kick-ops-on-error", DEFAULT_KICK_OPS_ON_ERROR);
        regionSupportEnable = config.getBoolean("region-support", DEFAULT_REGION_SUPPORT_ENABLE);

        // FIXME currently hidden option
        refreshTask.setDelay(config.getInt("bulk-refresh-delay", DEFAULT_BULK_REFRESH_DELAY));
        autoRefreshInterval = config.getInt("auto-refresh-interval", DEFAULT_AUTO_REFRESH_INTERVAL);
        autoRefreshForce = config.getBoolean("auto-refresh-force", DEFAULT_AUTO_REFRESH_FORCE);
        nativeVaultBridges = config.getBoolean("native-vault-bridges", DEFAULT_NATIVE_VAULT_BRIDGES);
        vaultPrefixIncludesGroup = config.getBoolean("vault-prefix-includes-group", DEFAULT_VAULT_PREFIX_INCLUDES_GROUP);
        vaultMetadataIncludesGroup = config.getBoolean("vault-metadata-includes-group", DEFAULT_VAULT_METADATA_INCLUDES_GROUP);
        vaultGroupTestUsesAssignedOnly = config.getBoolean("vault-group-test-uses-assigned-only", DEFAULT_VAULT_GROUP_TEST_USES_ASSIGNED_ONLY);
        vaultGetGroupsUsesAssignedOnly = config.getBoolean("vault-get-groups-uses-assigned-only", DEFAULT_VAULT_GET_GROUPS_USES_ASSIGNED_ONLY);
        vaultPlayerPrefixFormat = config.getString("vault-player-prefix-format", "");
        vaultPlayerSuffixFormat = config.getString("vault-player-suffix-format", "");
        logVaultChanges = config.getBoolean("log-vault-changes", DEFAULT_LOG_VAULT_CHANGES);
        inheritedMetadata = config.getBoolean("inherited-metadata", DEFAULT_INHERITED_METADATA);
        serviceMetadataPrefixHack = config.getBoolean("service-metadata-prefix-hack", DEFAULT_SERVICE_METADATA_PREFIX_HACK);
        // FIXME More hidden options
        searchBatchSize = config.getInt("search-batch-size", DEFAULT_SEARCH_BATCH_SIZE);
        searchDelay = config.getInt("search-delay", DEFAULT_SEARCH_DELAY);
        // FIXME UUID options, all hidden for now
        uuidResolverCacheSize = config.getInt("uuid-cache-size", DEFAULT_UUID_CACHE_SIZE);
        uuidResolverCacheTtl = config.getLong("uuid-cache-ttl", DEFAULT_UUID_CACHE_TTL);
        uuidMigrate = config.getBoolean("uuid-migrate", DEFAULT_UUID_MIGRATE);

        ToHDatabaseUtils.populateNamingConvention(config, namingConvention);

        // Region managers
        regionManagers = new ArrayList<>();
        strOrList = config.get("region-managers");
        if (strOrList != null) {
            if (strOrList instanceof String) {
                regionManagers.add((String)strOrList);
            }
            else if (strOrList instanceof List<?>) {
                for (Object obj : (List<?>)strOrList) {
                    if (obj instanceof String) {
                        regionManagers.add((String)obj);
                    }
                    else
                        warn(this, "region-managers list contains non-string value");
                }
            }
            else
                warn(this, "region-managers must be a string or list of strings");
        }
        else {
            // Set up default region manager(s)
            regionManagers.add("WorldGuard");
            regionManagers.add("Residence");
            regionManagers.add("Factoid");
        }

        configureWorldMirrors();

        storageStrategyClassName = config.getString("custom-storage-strategy");
    }

    private void configureWorldMirrors() {
        getResolver().clearWorldAliases();
        ConfigurationSection mirrors = config.getConfigurationSection("mirrors");
        boolean header = false;
        if (mirrors != null) {
            for (String target : mirrors.getKeys(false)) {
                List<?> list = mirrors.getList(target);
                if (list == null) {
                    warn(this, "Mirror %s must be a list", target);
                    continue;
                }

                for (Object o : list) {
                    getResolver().addWorldAlias(o.toString(), target);

                    if (!header) {
                        debug(this, "World mirrors:");
                        header = true;
                    }

                    debug(this, "  %s -> %s", o.toString(), target);
                }
            }
        }
    }

    /**
     * Re-read config.yml and refresh attachments of all online players.
     */
    @Override
    public void reload() {
        config = ToHFileUtils.getConfig(this);
        readConfig();
        startAutoRefreshTask();
        refresh(true, new Runnable() {
            @Override
            public void run() {
                invalidateMetadataCache();
                refreshPlayers();
                refreshExpirations();
            }
        });
    }

    /**
     * Refresh permissions store
     */
    @Override
    public void refresh(boolean force, Runnable finishTask) {
        storageStrategy.refresh(force, finishTask);
    }

    // Cancel existing auto-refresh task and start a new one if autoRefreshInterval is valid
    private void startAutoRefreshTask() {
        // Cancel previous task, if any
        if (autoRefreshTaskId > -1) {
            Bukkit.getScheduler().cancelTask(autoRefreshTaskId);
            autoRefreshTaskId = -1;
        }
        // Start up new task at new interval
        if (databaseSupport && autoRefreshInterval > 0) {
            final Plugin plugin = this;
            autoRefreshTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
                @Override
                public void run() {
                    log(plugin, "Refreshing from database...");
                    refresh(autoRefreshForce, new Runnable() {
                        @Override
                        public void run() {
                            // This is executed after the storage refresh is done.
                            log(plugin, "Refresh done.");
                            invalidateMetadataCache();
                            refreshPlayers();
                            refreshExpirations();
                        }
                    });
                }
            }, autoRefreshInterval * 20 * 60, autoRefreshInterval * 20 * 60); // FIXME magic numbers
        }
    }

    // Retrieve associated PlayerState, if any
    private PlayerState getPlayerState(Player player) {
        for (MetadataValue mv : player.getMetadata(PLAYER_METADATA_KEY)) {
            if (mv.getOwningPlugin() == this) {
                return (PlayerState)mv.value();
            }
        }
        return null;
    }

    // Encapsulates state about a player
    private static class PlayerState {

        private Set<String> regions;

        private String world;

        private Set<String> groups;

        public PlayerState(Set<String> regions, String world, Set<String> groups) {
            setRegions(regions);
            setWorld(world);
            setGroups(groups);
        }

        public void setRegions(Set<String> regions) {
            // NB should already be lower-cased
            this.regions = Collections.unmodifiableSet(new HashSet<>(regions));
        }

        public Set<String> getRegions() {
            return regions;
        }

        public String getWorld() {
            return world;
        }

        public Set<String> getGroups() {
            return groups;
        }

        public void setWorld(String world) {
            if (world == null)
                throw new IllegalArgumentException("world cannot be null");
            this.world = world;
        }

        public void setGroups(Set<String> groups) {
            this.groups = new HashSet<>(groups.size());
            for (String group : groups) {
                this.groups.add(group.toLowerCase());
            }
            this.groups = Collections.unmodifiableSet(this.groups);
        }

    }

    @Override
    public boolean handleException(CommandSender sender, Command command, String label, String[] args, Throwable t) {
        if (t instanceof ReadOnlyException) {
            sendMessage(sender, colorize("{RED}Server set to read-only mode."));
            abortBatchProcessing();
            return true;
        }
        return false;
    }

    @Override
    public void invalidateMetadataCache(String name, UUID uuid, boolean group) {
        metadataManager.invalidateMetadata(name, uuid, group);
    }

    @Override
    public void invalidateMetadataCache() {
        metadataManager.invalidateAllMetadata();
    }

    @Override
    public void logExternalChange(String message, Object... args) {
        if (logVaultChanges) {
            log(this, message, args);
        }
        else {
            debug(this, message, args);
        }
    }

    public int getSearchBatchSize() {
        return searchBatchSize;
    }

    public int getSearchDelay() {
        return searchDelay;
    }

    @Override
    public String getVaultPlayerPrefixFormat() {
        return vaultPlayerPrefixFormat;
    }

    @Override
    public String getVaultPlayerSuffixFormat() {
        return vaultPlayerSuffixFormat;
    }

    @Override
    public void updateDisplayName(final UUID uuid, final String displayName) {
        if (databaseReadOnly) return; // Do nothing if in read-only mode

        // Run synchronous since I'm not so sure about thread safety of AvajeStorageStrategy's
        // pre-commit hook...
        Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
            @Override
            public void run() {
                getRetryingTransactionStrategy().execute(new TransactionCallbackWithoutResult() {
                    @Override
                    public void doInTransactionWithoutResult() throws Exception {
                        getPermissionService().updateDisplayName(uuid, displayName);
                    }
                });
                // Also preload name -> UUID mapping into UuidResolver cache(s)
                uuidResolver.preload(displayName, uuid);
            }
        });
    }

    @Override
    public boolean isServiceMetadataPrefixHack() {
        return serviceMetadataPrefixHack;
    }

    @Override
    public void handleExplicitDefaultGroupMembership(final UUID uuid, final String displayName) {
        if (!explicitDefaultGroupMembership) return; // Keep things implicit

        final Plugin realThis = this;
        getRetryingTransactionStrategy().execute(new TransactionCallbackWithoutResult() {
            @Override
            public void doInTransactionWithoutResult() throws Exception {
                // Check if they are in any groups
                List<Membership> memberships = getPermissionService().getGroups(uuid);
                if (memberships.isEmpty()) {
                    // No groups, so add them
                    try {
                        debug(realThis, "Explicitly adding %s to default group %s", displayName, getResolver().getDefaultGroup());
                        getPermissionService().addMember(getResolver().getDefaultGroup(), uuid, displayName, null);
                    }
                    catch (MissingGroupException e) {
                        warn(realThis, "explicit-default-group-membership is true but the group (%s) does not exist; nothing done", getResolver().getDefaultGroup());
                    }

                    // No need to refresh or invalidate caches since they were
                    // already a member of this group.
                }
            }
        });
    }

}


text:
/*!
 * \file   embedded_string_type.hpp
 * \author Andrey Semashev
 * \date   16.08.2009
 *
 * This header is the Boost.Log library implementation, see the library documentation
 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
 */

#ifndef BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_

#include <string>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/header.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace aux {

template< typename T, typename ArgT >
struct make_embedded_string_type_impl
{
    typedef ArgT type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< char, ArgT >
{
    typedef std::basic_string< char > type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< const char, ArgT >
{
    typedef std::basic_string< char > type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< wchar_t, ArgT >
{
    typedef std::basic_string< wchar_t > type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< const wchar_t, ArgT >
{
    typedef std::basic_string< wchar_t > type;
};

#if !defined(BOOST_NO_CXX11_CHAR16_T)
template< typename ArgT >
struct make_embedded_string_type_impl< char16_t, ArgT >
{
    typedef std::basic_string< char16_t > type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< const char16_t, ArgT >
{
    typedef std::basic_string< char16_t > type;
};
#endif

#if !defined(BOOST_NO_CXX11_CHAR32_T)
template< typename ArgT >
struct make_embedded_string_type_impl< char32_t, ArgT >
{
    typedef std::basic_string< char32_t > type;
};

template< typename ArgT >
struct make_embedded_string_type_impl< const char32_t, ArgT >
{
    typedef std::basic_string< char32_t > type;
};
#endif

//! An auxiliary type translator to store strings by value in function objects and attribute values
template< typename ArgT >
struct make_embedded_string_type :
    public remove_cv< ArgT >
{
};

template< typename ArgT >
struct make_embedded_string_type< ArgT* > :
    public make_embedded_string_type_impl< ArgT, ArgT* >
{
};

template< typename ArgT, unsigned int CountV >
struct make_embedded_string_type< ArgT[CountV] > :
    public make_embedded_string_type_impl< ArgT, ArgT[CountV] >
{
};

template< typename ArgT, unsigned int CountV >
struct make_embedded_string_type< ArgT(&)[CountV] > :
    public make_embedded_string_type_impl< ArgT, ArgT(&)[CountV] >
{
};

} // namespace aux

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_