text:
package com.bumptech.glide.load.model;

import android.os.ParcelFileDescriptor;

import com.bumptech.glide.load.Encoder;

import java.io.InputStream;
import java.io.OutputStream;

/**
 * A source encoder that writes a {@link ImageVideoWrapper} to disk by preferentially
 * writing data from the wrapper's {@link InputStream} and falling back to the wrapper's
 * {@link ParcelFileDescriptor} if the {@link InputStream} isn't available.
 */
public class ImageVideoWrapperEncoder implements Encoder<ImageVideoWrapper> {
    private final Encoder<InputStream> streamEncoder;
    private final Encoder<ParcelFileDescriptor> fileDescriptorEncoder;
    private String id;

    public ImageVideoWrapperEncoder(Encoder<InputStream> streamEncoder,
            Encoder<ParcelFileDescriptor> fileDescriptorEncoder) {
        this.streamEncoder = streamEncoder;
        this.fileDescriptorEncoder = fileDescriptorEncoder;
    }

    @Override
    public boolean encode(ImageVideoWrapper data, OutputStream os) {
        if (data.getStream() != null) {
            return streamEncoder.encode(data.getStream(), os);
        } else {
            return fileDescriptorEncoder.encode(data.getFileDescriptor(), os);
        }
    }

    @Override
    public String getId() {
        if (id == null) {
            id = streamEncoder.getId() + fileDescriptorEncoder.getId();
        }
        return id;
    }
}

redpajama_set_name: RedPajamaGithub


text:
package com.gx.state

trait KeyboardState {
  def write(word: String): Unit
}

class UpperCaseState extends KeyboardState {
  override def write(word: String): Unit = {
    println(word.toUpperCase)
  }
}

class LowerCaseState extends KeyboardState {
  override def write(word: String): Unit = {
    println(word.toLowerCase)
  }
}


text:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UtauLib;

namespace BulkEnvelopeEditor.Tests {

	[TestClass]
	public class NoteTests {

		public string[] processSounds = { "b", "br", "br6", "br666", "in", "inex", ".", "x" };
		public string[] skipSounds = { "", "ba", "mi", "ま", "brederp", "brea", "i", "xyz", "xx" };

		private bool IsBreath(string lyric) {

			var note = new Note { Lyric = lyric };
			return note.IsBreathOrRest;

		}

		[TestMethod]
		public void TestValidSounds() {

			foreach (var validSound in processSounds) {
				Assert.IsTrue(IsBreath(validSound), validSound);
			}

		}

		[TestMethod]
		public void TestSkipSounds() {

			foreach (var skipSound in skipSounds) {
				Assert.IsFalse(IsBreath(skipSound), skipSound);
			}

		}

	}
}


text:
/* @test
 * @bug 4313882 4981129
 * @summary Unit test for datagram-socket-channel adaptors
 * @library ..
 */

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;

public class AdaptDatagramSocket {

    static java.io.PrintStream out = System.out;

    static Random rand = new Random();

    static final int ECHO_PORT = 7;
    static final int DISCARD_PORT = 9;
    static final String REMOTE_HOST = TestUtil.HOST;

    static final InetSocketAddress echoAddress
        = new InetSocketAddress(REMOTE_HOST, ECHO_PORT);
    static final InetSocketAddress discardAddress
        = new InetSocketAddress(REMOTE_HOST, DISCARD_PORT);

    static String toString(DatagramPacket dp) {
        return ("DatagramPacket[off=" + dp.getOffset()
                + ", len=" + dp.getLength()
                + "]");
    }

    static void test(DatagramSocket ds, InetSocketAddress dst,
                     boolean shouldTimeout)
        throws Exception
    {
        DatagramPacket op = new DatagramPacket(new byte[100], 13, 42, dst);
        rand.nextBytes(op.getData());
        DatagramPacket ip = new DatagramPacket(new byte[100], 19, 100 - 19);
        out.println("pre  op: " + toString(op) + "  ip: " + toString(ip));

        long start = System.currentTimeMillis();
        ds.send(op);

        for (;;) {
            try {
                ds.receive(ip);
                if (ip.getLength() == 0) { // ## Not sure why this happens
                    ip.setLength(100 - 19);
                    continue;
                }
            } catch (SocketTimeoutException x) {
                if (shouldTimeout) {
                    out.println("Receive timed out, as expected");
                    return;
                }
                throw x;
            }
            break;
        }

        out.println("rtt: " + (System.currentTimeMillis() - start));
        out.println("post op: " + toString(op) + "  ip: " + toString(ip));

        for (int i = 0; i < ip.getLength(); i++)
            if (ip.getData()[ip.getOffset() + i]
                != op.getData()[op.getOffset() + i])
                throw new Exception("Incorrect data received");

        if (!(ip.getSocketAddress().equals(dst))) {
            throw new Exception("Incorrect sender address, expected: " + dst
                + " actual: " + ip.getSocketAddress());
        }
    }

    static void test(InetSocketAddress dst,
                     int timeout, boolean shouldTimeout,
                     boolean connect)
        throws Exception
    {
        out.println();
        out.println("dst: " + dst);

        DatagramSocket ds;
        if (false) {
            // Original
            ds = new DatagramSocket();
        } else {
            DatagramChannel dc = DatagramChannel.open();
            ds = dc.socket();
            ds.bind(new InetSocketAddress(0));
        }

        out.println("socket: " + ds);
        if (connect) {
            ds.connect(dst);
            out.println("connect: " + ds);
        }
        InetSocketAddress src = new InetSocketAddress(ds.getLocalAddress(),
                                                      ds.getLocalPort());
        out.println("src: " + src);

        if (timeout > 0)
            ds.setSoTimeout(timeout);
        out.println("timeout: " + ds.getSoTimeout());

        for (int i = 0; i < 5; i++)
            test(ds, dst, shouldTimeout);

        // Leave the socket open so that we don't reuse the old src address
        //ds.close();

    }

    public static void main(String[] args) throws Exception {
        test(echoAddress, 0, false, false);
        test(echoAddress, 0, false, true);
        test(echoAddress, 5000, false, false);
        test(discardAddress, 10, true, false);
    }

}


text:
package org.uberfire.ext.wires.core.grids.client.widget.grid.animation;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.ait.lienzo.client.core.shape.IPrimitive;
import com.ait.lienzo.client.core.shape.Layer;
import com.google.gwt.user.client.Command;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.uberfire.ext.wires.core.grids.client.widget.grid.GridWidget;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class GridWidgetEnterPinnedModeAnimationTest {

    @Mock
    private Layer layer;

    @Mock
    private GridWidget gridWidget;

    @Mock
    private Command onStartCommand;

    @Mock
    private GridWidget widget;

    @Mock
    private IPrimitive<?> primitive;

    @Mock
    private Command command;

    @Test
    public void testOnClose() {

        doReturn(layer).when(gridWidget).getLayer();

        final Set<GridWidget> gridWidgets = new HashSet<GridWidget>() {{
            add(widget);
        }};
        final Set<IPrimitive<?>> gridWidgetConnectors = new HashSet<IPrimitive<?>>() {{
            add(primitive);
        }};
        final List<Command> onEnterPinnedModeCommands = new ArrayList<Command>() {{
            add(command);
        }};
        final GridWidgetEnterPinnedModeAnimation animation = new GridWidgetEnterPinnedModeAnimation(gridWidget,
                                                                                gridWidgets,
                                                                                gridWidgetConnectors,
                                                                                onStartCommand,
                                                                                onEnterPinnedModeCommands);

        animation.doClose();

        verify(widget).setVisible(false);
        verify(primitive).setVisible(false);
        verify(layer).setListening(true);
        verify(layer).batch();
        verify(command).execute();
    }
}


text:
<<<<<<< HEAD
<?php
// +----------------------------------------------------------------------
// | Copyright (c) 2015 http://www.happychou.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author:  zhouht (zhouht@happychou.net)
// +----------------------------------------------------------------------
namespace Common\Model;
use Think\Model;
class ItemCollectModel extends Model {
	protected $_validate = array(
	    array('uin','require','投资人uin不存在!',0),
	    array('itemid','require','项目id不存在',1),
	);
	protected $_auto = array (
         array('uin','getUin',1,'callback'),
         array('time','time',1,'function'),
     );
	//自动完成uin
	protected function getUin(){
		return $_SESSION['user']['uin'];
	}
	/**
     * 读取信息
     * @return array 信息
     */
	public function getInfo($where,$order = 'time desc'){
		return M('item_collect as a')->where($where)->order($order)->find();
	}
	/**
     * 读取列表数据
     * @return array 列表
     */
	public function loadList($where = array(), $limit = 10 ,$order = 'time desc'){
		return 	M('item_collect as a')
				->join('LEFT JOIN __ITEM__ b ON a.itemid = b.id')
				->join('LEFT JOIN __ITEM_PROGRESS__ c ON b.progress = c.id')
				->join('LEFT JOIN __USER__ d ON a.uin = d.uin')
				->field('a.*,b.name as item_name,b.cover_img, b.desc,b.raising_money,b.investment_rate,b.lowest_money,c.name as progress_name,d.name as user_name, header')
				->where($where)
				->limit($limit)
				->order($order)
				->select();
	}
	/**
     * 获取数量
     * @return int 数量
     */
    public function countList($where = array()){
        return 	M('item_collect as a')
        		->join('LEFT JOIN __ITEM__ b ON a.itemid = b.id')
        		->where($where)
                ->count();
    }

	//获取用户收藏项目数量
	public function getusercollectnum($where){
         return M('item_collect')->where($where)->count();
	}

=======
<?php
// +----------------------------------------------------------------------
// | Copyright (c) 2015 http://www.happychou.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author:  zhouht (zhouht@happychou.net)
// +----------------------------------------------------------------------
namespace Common\Model;
use Think\Model;
class ItemCollectModel extends Model {
	protected $_validate = array(
	    array('uin','require','投资人uin不存在!',0),
	    array('itemid','require','项目id不存在',1),
	);
	protected $_auto = array (
         array('uin','getUin',1,'callback'),
         array('time','time',1,'function'),
     );
	//自动完成uin
	protected function getUin(){
		return $_SESSION['user']['uin'];
	}
	/**
     * 读取信息
     * @return array 信息
     */
	public function getInfo($where,$order = 'time desc'){
		return M('item_collect as a')->where($where)->order($order)->find();
	}
	/**
     * 读取列表数据
     * @return array 列表
     */
	public function loadList($where = array(), $limit = 10 ,$order = 'time desc'){
		return 	M('item_collect as a')
				->join('LEFT JOIN __ITEM__ b ON a.itemid = b.id')
				->join('LEFT JOIN __ITEM_PROGRESS__ c ON b.progress = c.id')
				->join('LEFT JOIN __USER__ d ON a.uin = d.uin')
				->field('a.*,b.name as item_name,b.cover_img, b.desc,b.raising_money,b.investment_rate,b.lowest_money,c.name as progress_name,d.name as user_name, header')
				->where($where)
				->limit($limit)
				->order($order)
				->select();
	}
	/**
     * 获取数量
     * @return int 数量
     */
    public function countList($where = array()){
        return 	M('item_collect as a')
        		->join('LEFT JOIN __ITEM__ b ON a.itemid = b.id')
        		->where($where)
                ->count();
    }

	//获取用户收藏项目数量
	public function getusercollectnum($where){
         return M('item_collect')->where($where)->count();
	}

>>>>>>> 98b56c4fd74d8c0bc5ebc0c352b176e8d8f7d926
}


text:
package com.tapit.vastsdk;

import android.content.Context;
import android.telephony.TelephonyManager;
import android.webkit.WebSettings;
import android.webkit.WebView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Constructor;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

public class TVASTUtils {

    private static String userAgent = null;

    public static String scrape(String resp, String start, String stop) {
        int offset, len;
        if ((offset = resp.indexOf(start)) < 0)
            return "";
        if ((len = resp.indexOf(stop, offset + start.length())) < 0)
            return "";
        return resp.substring(offset + start.length(), len);
    }

    public static String md5(String data) {
        try {
            MessageDigest digester = MessageDigest.getInstance("MD5");
            digester.update(data.getBytes());
            byte[] messageDigest = digester.digest();
            return TVASTUtils.byteArrayToHexString(messageDigest);
        } catch (NoSuchAlgorithmException e) {
        }
        return null;
    }

    public static String byteArrayToHexString(byte[] array) {
        StringBuffer hexString = new StringBuffer();
        for (byte b : array) {
            int intVal = b & 0xff;
            if (intVal < 0x10)
                hexString.append("0");
            hexString.append(Integer.toHexString(intVal));
        }
        return hexString.toString();
    }

    public static String getUserAgentString(Context context) {
        if (userAgent == null) {
            try {
                Constructor<WebSettings> constructor = WebSettings.class.getDeclaredConstructor(
                        Context.class, WebView.class);
                constructor.setAccessible(true);
                try {
                    WebSettings settings = constructor.newInstance(context, null);
                    userAgent = settings.getUserAgentString();
                } finally {
                    constructor.setAccessible(false);
                }
            } catch (Exception e) {
                userAgent = new WebView(context).getSettings().getUserAgentString();
            }
        }
        return userAgent;
    }

    private static String sID = null;
    private static final String INSTALLATION = "INSTALLATION";

    public synchronized static String id(Context context) {
        if (sID == null) {
            File installation = new File(context.getFilesDir(), INSTALLATION);
            try {
                if (!installation.exists())
                    writeInstallationFile(installation);
                sID = readInstallationFile(installation);
            } catch (Exception e) {
                // throw new RuntimeException(e);
                sID = "1234567890";
            }
        }
        return sID;
    }

    private static String readInstallationFile(File installation) throws IOException {
        RandomAccessFile f = new RandomAccessFile(installation, "r");
        byte[] bytes = new byte[(int) f.length()];
        f.readFully(bytes);
        f.close();
        return new String(bytes);
    }

    private static void writeInstallationFile(File installation) throws IOException {
        FileOutputStream out = new FileOutputStream(installation);
        String id = UUID.randomUUID().toString();
        out.write(id.getBytes());
        out.close();
    }

    public static String getDeviceId(Context context) {
        // Interesting discussion about getting a DeviceId
        // http://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            String deviceId = tm.getDeviceId();
            if (deviceId == null) {
                deviceId = TVASTUtils.id(context);
            }
//			return Utils.md5(deviceId);
            return deviceId;
        } catch (SecurityException e) {
            return "unknown";
        }
        // An alternate implementation that doesn't require the READ_PHONE_STATE permission
//        String deviceId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
//        if(deviceId != null) {
//        	deviceId = Utils.md5(deviceId);
//        }
//
//        return deviceId;
    }

    public static String getDeviceIdMD5(Context context) {
        String udid = getDeviceId(context);
        if (udid != "unknown") {
            udid = TVASTUtils.md5(udid);
        }
        return udid;
    }

    public static String getCarrier(Context context) {
        TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return manager.getNetworkOperatorName();
    }
}


text:
using namespace System;

int main(array<System::String ^> ^args)
{
  // TODO: start development
    Console::WriteLine(L"Hello World");
    return 0;
}


text:
package org.hippoecm.repository;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.junit.Test;
import org.onehippo.repository.testutils.RepositoryTestCase;

import static org.junit.Assert.assertNotNull;

public class AuthorizationSanityTest extends RepositoryTestCase {

    private void visit(Node node, Session check) throws RepositoryException {
        if(node.getDepth() > 0 && check.itemExists(node.getPath())) {
            assertNotNull("should be able to reach node "+node.getPath(), traverse(check, node.getPath()));
        }
        for(NodeIterator iter = node.getNodes(); iter.hasNext(); ) {
            visit(iter.nextNode(), check);
        }
    }

    @Test
    public void testTraversability() throws Exception {
        Node root = session.getRootNode();
        Session anonymous = server.login();
        assertNotNull(anonymous);
        visit(root, anonymous);
    }
}


text:
"""
The ``discoursegraph`` module specifies a ``DisourseDocumentGraph``,
the fundamential data structure used in this package. It is a slightly
modified ``networkx.MultiDiGraph``, which enforces every node and edge to have
a ``layers`` attribute (which maps to the set of layers (str) it belongs to).

TODO: implement a DiscourseCorpusGraph
"""

import itertools
import sys
import warnings
from collections import defaultdict, OrderedDict

from networkx import MultiGraph, MultiDiGraph, is_directed_acyclic_graph

from discoursegraphs.relabel import relabel_nodes
from discoursegraphs.util import natural_sort_key

class EdgeTypes(object):
    """Enumerator of edge types"""
    pointing_relation = 'points_to'
    # reverse_pointing_relation = 'is_pointed_to_by' # not needed right now
    dominance_relation = 'dominates'
    reverse_dominance_relation = 'is_dominated_by'
    spanning_relation = 'spans'
    # reverse_spanning_relation = 'is_part_of' # not needed right now
    precedence_relation = 'precedes'

class DiscourseDocumentGraph(MultiDiGraph):
    """
    Base class for representing annotated documents as directed graphs
    with multiple edges.

    Attributes
    ----------
    ns : str
        the namespace of the graph (default: discoursegraph)
    root : str
        name of the document root node ID
        (default: self.ns+':root_node')
    sentences : list of str
        sorted list of all sentence root node IDs (of sentences
        contained in this document graph -- iff the document was annotated
        for sentence boundaries in one of the layers present in this graph)
    tokens : list of int
        a list of node IDs (int) which represent the tokens in the
        order they occur in the text

    TODO list:

    - allow layers to be a single str or set of str
    - allow adding a layer by including it in ``**attr``
    - add consistency check that would allow adding a node that
      already exists in the graph, but only if the new graph has
      different attributes (layers can be the same though)
    - outsource layer assertions to method?
    """

    # Create a multdigraph object that tracks the order nodes are added
    # and for each node track the order that neighbors are added and for
    # each neighbor tracks the order that multiedges are added.
    # Cf. nx.MultiDiGraph docstring (OrderedGraph)
    node_dict_factory = OrderedDict
    adjlist_dict_factory = OrderedDict
    edge_key_dict_factory = OrderedDict

    def __init__(self, name='', namespace='discoursegraph', root=None):
        """
        Initialized an empty directed graph which allows multiple edges.

        Parameters
        ----------
        name : str or None
            name or ID of the graph to be generated.
        namespace : str
            namespace of the graph (default: discoursegraph)
        root : str or None
            Name of the root node. If None, defaults to namespace+':root_node'.
        """
        # super calls __init__() of base class MultiDiGraph
        super(DiscourseDocumentGraph, self).__init__()
        self.name = name
        self.ns = namespace
        self.root = root if root else self.ns+':root_node'
        self.add_node(self.root, layers={self.ns})
        # metadata shall be stored in the root node's dictionary
        self.node[self.root]['metadata'] = defaultdict(lambda: defaultdict(dict))
        self.sentences = []
        self.tokens = []

    def add_offsets(self, offset_ns=None):
        """
        adds the onset and offset to each token in the document graph, i.e.
        the character position where each token starts and ends.
        """
        if offset_ns is None:
            offset_ns = self.ns

        onset = 0
        offset = 0

        for token_id, token_str in self.get_tokens():
            offset = onset + len(token_str)
            self.node[token_id]['{0}:{1}'.format(offset_ns, 'onset')] = onset
            self.node[token_id]['{0}:{1}'.format(offset_ns, 'offset')] = offset
            onset = offset + 1

    def get_offsets(self, token_node_id=None, offset_ns=None):
        """
        returns the offsets (character starting and end position) of a token
        or of all tokens occurring in the document.

        Parameters
        ----------
        token_node_id : str, int or None
            Node ID of a token from which we want to retrieve the start and end
            position. If no node ID is given, this method will yield
            (token node ID, start pos, end pos) tuples containing data for all
            tokens in the document
        offset_ns : str or None
            The namespace from which the offsets will be retrieved. If no
            namespace is given, the default namespace of this document graph is
            chosen

        Returns
        -------
        offsets : tuple(int, int) or generator(tuple(str, int, int))
            If a token node ID is given, a (character onset int, character
            offset int) tuple is returned. Otherwise, a generator of (token
            node ID str, character onset int, character offset int) tuples
            will be returned, representing all the tokens in the order they
            occur in the document.
        """
        if offset_ns is None:
            offset_ns = self.ns

        try:
            if token_node_id is not None:
                assert istoken(self, token_node_id), \
                    "'{}' is not a token node.".format(token_node_id)
                onset = self.node[token_node_id]['{0}:{1}'.format(offset_ns, 'onset')]
                offset = self.node[token_node_id]['{0}:{1}'.format(offset_ns, 'offset')]
                return (onset, offset)
            else:  # return offsets for all tokens in the document
                return self._get_all_offsets(offset_ns)

        # if the document doesn't have offsets: add them and rerun this method
        except KeyError as e:
            self.add_offsets(offset_ns)
            return self.get_offsets(token_node_id, offset_ns)

    def _get_all_offsets(self, offset_ns=None):
        """
        returns all token offsets of this document as a generator of
        (token node ID str, character onset int, character offset int) tuples.

        Parameters
        ----------
        offset_ns : str or None
            The namespace from which the offsets will be retrieved. If no
            namespace is given, the default namespace of this document graph is
            chosen

        Returns
        -------
        offsets : generator(tuple(str, int, int))
            a generator of (token node ID str, character onset int, character
            offset int) tuples, which represents all the tokens in the order
            they occur in the document.
        """
        for token_id, _token_str in self.get_tokens():
            onset = self.node[token_id]['{0}:{1}'.format(offset_ns, 'onset')]
            offset = self.node[token_id]['{0}:{1}'.format(offset_ns, 'offset')]
            yield (token_id, onset, offset)

    def get_phrases(self, ns=None, layer='syntax', cat_key='cat', cat_val='NP'):
        """yield all node IDs that dominate the given phrase type, e.g. all NPs"""
        if not ns:
            ns = self.ns

        for node_id in select_nodes_by_layer(self, '{0}:{1}'.format(ns, layer)):
            if self.node[node_id][self.ns+':'+cat_key] == cat_val:
                yield node_id

    def add_node(self, n, layers=None, attr_dict=None, **attr):
        """Add a single node n and update node attributes.

        Parameters
        ----------
        n : node
            A node can be any hashable Python object except None.
        layers : set of str or None
            the set of layers the node belongs to,
            e.g. {'tiger:token', 'anaphoricity:annotation'}.
            Will be set to {self.ns} if None.
        attr_dict : dictionary, optional (default= no attributes)
            Dictionary of node attributes.  Key/value pairs will
            update existing data associated with the node.
        attr : keyword arguments, optional
            Set or change attributes using key=value.

        See Also
        --------
        add_nodes_from

        Examples
        --------
        >>> from discoursegraphs import DiscourseDocumentGraph
        >>> d = DiscourseDocumentGraph()
        >>> d.add_node(1, {'node'})

        # adding the same node with a different layer
        >>> d.add_node(1, {'number'})
        >>> d.nodes(data=True)
        [(1, {'layers': {'node', 'number'}})]

        Use keywords set/change node attributes:

        >>> d.add_node(1, {'node'}, size=10)
        >>> d.add_node(3, layers={'num'}, weight=0.4, UTM=('13S',382))
        >>> d.nodes(data=True)
        [(1, {'layers': {'node', 'number'}, 'size': 10}),
         (3, {'UTM': ('13S', 382), 'layers': {'num'}, 'weight': 0.4})]

        Notes
        -----
        A hashable object is one that can be used as a key in a Python
        dictionary. This includes strings, numbers, tuples of strings
        and numbers, etc.

        On many platforms hashable items also include mutables such as
        NetworkX Graphs, though one should be careful that the hash
        doesn't change on mutables.
        """
        if not layers:
            layers = {self.ns}
        assert isinstance(layers, set), \
            "'layers' parameter must be given as a set of strings."
        assert all((isinstance(layer, str) for layer in layers)), \
            "All elements of the 'layers' set must be strings."
        # add layers to keyword arguments dict
        attr.update({'layers': layers})

        # set up attribute dict
        if attr_dict is None:
            attr_dict = attr
        else:
            assert isinstance(attr_dict, dict), \
                "attr_dict must be a dictionary, not a '{}'".format(type(attr_dict))
            attr_dict.update(attr)

        # if there's no node with this ID in the graph, yet
        if n not in self.succ:
            self.succ[n] = {}
            self.pred[n] = {}
            self.node[n] = attr_dict
        else:  # update attr even if node already exists
            # if a node exists, its attributes will be updated, except
            # for the layers attribute. the value of 'layers' will
            # be the union of the existing layers set and the new one.
            existing_layers = self.node[n]['layers']
            all_layers = existing_layers.union(layers)
            attrs_without_layers = {k: v for (k, v) in attr_dict.items()
                                    if k != 'layers'}
            self.node[n].update(attrs_without_layers)
            self.node[n].update({'layers': all_layers})

    def add_nodes_from(self, nodes, **attr):
        """Add multiple nodes.

        Parameters
        ----------
        nodes : iterable container
            A container of nodes (list, dict, set, etc.).
            OR
            A container of (node, attribute dict) tuples.
            Node attributes are updated using the attribute dict.
        attr : keyword arguments, optional (default= no attributes)
            Update attributes for all nodes in nodes.
            Node attributes specified in nodes as a tuple
            take precedence over attributes specified generally.

        See Also
        --------
        add_node

        Examples
        --------
        >>> from discoursegraphs import DiscourseDocumentGraph
        >>> d = DiscourseDocumentGraph()
        >>> d.add_nodes_from([(1, {'layers':{'token'}, 'word':'hello'}), \
                (2, {'layers':{'token'}, 'word':'world'})])
        >>> d.nodes(data=True)
        [(1, {'layers': {'token'}, 'word': 'hello'}),
         (2, {'layers': {'token'}, 'word': 'world'})]

        Use keywords to update specific node attributes for every node.

        >>> d.add_nodes_from(d.nodes(data=True), weight=1.0)
        >>> d.nodes(data=True)
        [(1, {'layers': {'token'}, 'weight': 1.0, 'word': 'hello'}),
         (2, {'layers': {'token'}, 'weight': 1.0, 'word': 'world'})]

        Use (node, attrdict) tuples to update attributes for specific
        nodes.

        >>> d.add_nodes_from([(1, {'layers': {'tiger'}})], size=10)
        >>> d.nodes(data=True)
        [(1, {'layers': {'tiger', 'token'}, 'size': 10, 'weight': 1.0,
              'word': 'hello'}),
         (2, {'layers': {'token'}, 'weight': 1.0, 'word': 'world'})]
        """
        additional_attribs = attr  # will be added to each node
        for n in nodes:
            try:  # check, if n is a node_id or a (node_id, attrib dict) tuple
                newnode = n not in self.succ  # is node in the graph, yet?
            except TypeError:  # n is a (node_id, attribute dict) tuple
                node_id, ndict = n

                if not 'layers' in ndict:
                    ndict['layers'] = {self.ns}

                layers = ndict['layers']
                assert isinstance(layers, set), \
                    "'layers' must be specified as a set of strings."
                assert all((isinstance(layer, str) for layer in layers)), \
                    "All elements of the 'layers' set must be strings."

                if node_id not in self.succ:  # node doesn't exist, yet
                    self.succ[node_id] = {}
                    self.pred[node_id] = {}
                    newdict = additional_attribs.copy()
                    newdict.update(ndict)  # all given attribs incl. layers
                    self.node[node_id] = newdict
                else:  # node already exists
                    existing_layers = self.node[node_id]['layers']
                    all_layers = existing_layers.union(layers)

                    self.node[node_id].update(ndict)
                    self.node[node_id].update(additional_attribs)
                    self.node[node_id].update({'layers': all_layers})
                continue  # process next node

            # newnode check didn't raise an exception
            if newnode:  # n is a node_id and it's not in the graph, yet
                self.succ[n] = {}
                self.pred[n] = {}
                self.node[n] = attr.copy()
                # since the node isn't represented as a
                # (node_id, attribute dict) tuple, we don't know which layers
                # it is part of. Therefore, we'll add the namespace of the
                # graph as the node layer
                self.node[n].update({'layers': set([self.ns])})
            else:  # n is a node_id and it's already in the graph
                self.node[n].update(attr)

    def add_edge(self, u, v, layers=None, key=None, attr_dict=None, **attr):
        """Add an edge between u and v.

        An edge can only be added if the nodes u and v already exist.
        This decision was taken to ensure that all nodes are associated
        with at least one (meaningful) layer.

        Edge attributes can be specified with keywords or by providing
        a dictionary with key/value pairs. In contrast to other
        edge attributes, layers can only be added not overwriten or
        deleted.

        Parameters
        ----------
        u,v : nodes
            Nodes can be, for example, strings or numbers.
            Nodes must be hashable (and not None) Python objects.
        layers : set of str
            the set of layers the edge belongs to,
            e.g. {'tiger:token', 'anaphoricity:annotation'}.
            Will be set to {self.ns} if None.
        key : hashable identifier, optional (default=lowest unused integer)
            Used to distinguish multiedges between a pair of nodes.
        attr_dict : dictionary, optional (default= no attributes)
            Dictionary of edge attributes.  Key/value pairs will
            update existing data associated with the edge.
        attr : keyword arguments, optional
            Edge data (or labels or objects) can be assigned using
            keyword arguments.

        See Also
        --------
        add_edges_from : add a collection of edges

        Notes
        -----
        To replace/update edge data, use the optional key argument
        to identify a unique edge.  Otherwise a new edge will be created.

        NetworkX algorithms designed for weighted graphs cannot use
        multigraphs directly because it is not clear how to handle
        multiedge weights.  Convert to Graph using edge attribute
        'weight' to enable weighted graph algorithms.

        Examples
        --------
        >>> from discoursegraphs import  DiscourseDocumentGraph
        >>> d = DiscourseDocumentGraph()
        >>> d.add_nodes_from([(1, {'layers':{'token'}, 'word':'hello'}), \
                (2, {'layers':{'token'}, 'word':'world'})])

        >>> d.edges(data=True)
        >>> []

        >>> d.add_edge(1, 2, layers={'generic'})

        >>> d.add_edge(1, 2, layers={'tokens'}, weight=0.7)

        >>> d.edges(data=True)
        [(1, 2, {'layers': {'generic'}}),
         (1, 2, {'layers': {'tokens'}, 'weight': 0.7})]

        >>> d.edge[1][2]
        {0: {'layers': {'generic'}}, 1: {'layers': {'tokens'}, 'weight': 0.7}}

        >>> d.add_edge(1, 2, layers={'tokens'}, key=1, weight=1.0)
        >>> d.edges(data=True)
        [(1, 2, {'layers': {'generic'}}),
         (1, 2, {'layers': {'tokens'}, 'weight': 1.0})]

        >>> d.add_edge(1, 2, layers={'foo'}, key=1, weight=1.0)
        >>> d.edges(data=True)
        [(1, 2, {'layers': {'generic'}}),
         (1, 2, {'layers': {'foo', 'tokens'}, 'weight': 1.0})]
        """
        if not layers:
            layers = {self.ns}
        assert isinstance(layers, set), \
            "'layers' parameter must be given as a set of strings."
        assert all((isinstance(layer, str) for layer in layers)), \
            "All elements of the 'layers' set must be strings."
        # add layers to keyword arguments dict
        attr.update({'layers': layers})

        # set up attribute dict
        if attr_dict is None:
            attr_dict = attr
        else:
            try:
                attr_dict.update(attr)
            except AttributeError as e:
                raise AttributeError("The attr_dict argument must be "
                                     "a dictionary: ".format(e))
        for node in (u, v):  # u = source, v = target
            if node not in self.nodes_iter():
                self.add_node(node, layers={self.ns})

        if v in self.succ[u]:  # if there's already an edge from u to v
            keydict = self.adj[u][v]
            if key is None:  # creating additional edge
                # find a unique integer key
                # other methods might be better here?
                key = len(keydict)
                while key in keydict:
                    key += 1
            datadict = keydict.get(key, {})  # works for existing & new edge
            existing_layers = datadict.get('layers', set())
            all_layers = existing_layers.union(layers)

            datadict.update(attr_dict)
            datadict.update({'layers': all_layers})
            keydict[key] = datadict

        else:  # there's no edge between u and v, yet
            # selfloops work this way without special treatment
            if key is None:
                key = 0
            datadict = {}
            datadict.update(attr_dict)  # includes layers
            keydict = {key: datadict}
            self.succ[u][v] = keydict
            self.pred[v][u] = keydict

    def add_edges_from(self, ebunch, attr_dict=None, **attr):
        """Add all the edges in ebunch.

        Parameters
        ----------
        ebunch : container of edges
            Each edge given in the container will be added to the
            graph. The edges can be:

                - 3-tuples (u,v,d) for an edge attribute dict d, or
                - 4-tuples (u,v,k,d) for an edge identified by key k

            Each edge must have a layers attribute (set of str).
        attr_dict : dictionary, optional  (default= no attributes)
            Dictionary of edge attributes.  Key/value pairs will
            update existing data associated with each edge.
        attr : keyword arguments, optional
            Edge data (or labels or objects) can be assigned using
            keyword arguments.

        See Also
        --------
        add_edge : add a single edge

        Notes
        -----
        Adding the same edge twice has no effect but any edge data
        will be updated when each duplicate edge is added.

        An edge can only be added if the source and target nodes are
        already present in the graph. This decision was taken to ensure
        that all edges are associated with at least one (meaningful)
        layer.

        Edge attributes specified in edges as a tuple (in ebunch) take
        precedence over attributes specified otherwise (in attr_dict or
        attr). Layers can only be added (via a 'layers' edge attribute),
        but not overwritten.

        Examples
        --------
        >>> d = DiscourseDocumentGraph()
        >>> d.add_node(1, {'int'})
        >>> d.add_node(2, {'int'})

        >>> d.add_edges_from([(1, 2, {'layers': {'int'}, 'weight': 23})])
        >>> d.add_edges_from([(1, 2, {'layers': {'int'}, 'weight': 42})])

        >>> d.edges(data=True) # multiple edges between the same nodes
        [(1, 2, {'layers': {'int'}, 'weight': 23}),
         (1, 2, {'layers': {'int'}, 'weight': 42})]

        Associate data to edges

        We update the existing edge (key=0) and overwrite its 'weight'
        value. Note that we can't overwrite the 'layers' value, though.
        Instead, they are added to the set of existing layers

        >>> d.add_edges_from([(1, 2, 0, {'layers':{'number'}, 'weight':66})])
        [(1, 2, {'layers': {'int', 'number'}, 'weight': 66}),
         (1, 2, {'layers': {'int'}, 'weight': 42})]
        """
        # set up attribute dict
        if attr_dict is None:
            attr_dict = attr
        else:
            try:
                attr_dict.update(attr)
            except AttributeError as e:
                raise AttributeError("The attr_dict argument must be "
                                     "a dictionary: ".format(e))
        # process ebunch
        for e in ebunch:
            ne = len(e)
            if ne == 4:
                u, v, key, dd = e
            elif ne == 3:
                u, v, dd = e
                key = None
            else:
                raise AttributeError(
                    "Edge tuple {0} must be a 3-tuple (u,v,attribs) "
                    "or 4-tuple (u,v,key,attribs).".format(e))

            if not 'layers' in dd:
                dd['layers'] = {self.ns}

            layers = dd['layers']
            assert isinstance(layers, set), \
                "'layers' must be specified as a set of strings."
            assert all((isinstance(layer, str)
                        for layer in layers)), \
                "All elements of the 'layers' set must be strings."
            additional_layers = attr_dict.get('layers', {})
            if additional_layers:
                assert isinstance(additional_layers, set), \
                    "'layers' must be specified as a set of strings."
                assert all((isinstance(layer, str)
                            for layer in additional_layers)), \
                    "'layers' set must only contain strings."
            # union of layers specified in ebunch tuples,
            # attr_dict and **attr
            new_layers = layers.union(additional_layers)

            if u in self.adj:  # edge with u as source already exists
                keydict = self.adj[u].get(v, {})
            else:
                keydict = {}
            if key is None:
                # find a unique integer key
                # other methods might be better here?
                key = len(keydict)
                while key in keydict:
                    key += 1
            datadict = keydict.get(key, {})  # existing edge attribs
            existing_layers = datadict.get('layers', set())
            datadict.update(attr_dict)
            datadict.update(dd)
            updated_attrs = {k: v for (k, v) in datadict.items()
                             if k != 'layers'}

            all_layers = existing_layers.union(new_layers)
            # add_edge() checks if u and v exist, so we don't need to
            self.add_edge(u, v, layers=all_layers, key=key,
                          attr_dict=updated_attrs)

    def add_layer(self, element, layer):
        """
        add a layer to an existing node or edge

        Parameters
        ----------
        element : str, int, (str/int, str/int)
            the ID of a node or edge (source node ID, target node ID)
        layer : str
            the layer that the element shall be added to
        """
        assert isinstance(layer, str), "Layers must be strings!"
        if isinstance(element, tuple): # edge repr. by (source, target)
            assert len(element) == 2
            assert all(isinstance(node, (str, int)) for node in element)
            source_id, target_id = element
            # this class is based on a multi-digraph, so we'll have to iterate
            # over all edges between the two nodes (even if there's just one)
            edges = self.edge[source_id][target_id]
            for edge in edges:
                existing_layers = edges[edge]['layers']
                existing_layers.add(layer)
                edges[edge]['layers'] = existing_layers
        if isinstance(element, (str, int)): # node
            existing_layers = self.node[element]['layers']
            existing_layers.add(layer)
            self.node[element]['layers'] = existing_layers

    def get_token(self, token_node_id, token_attrib='token'):
        """
        given a token node ID, returns the token unicode string.

        Parameters
        ----------
        token_node_id : str
            the ID of the token node
        token_attrib : str
            name of the node attribute that contains the token string as its
            value (default: token).

        Returns
        -------
        token : unicode
            the token string
        """
        return self.node[token_node_id][self.ns+':'+token_attrib]

    def get_tokens(self, token_attrib='token', token_strings_only=False):
        """
        returns a list of (token node ID, token) which represent the tokens
        of the input document (in the order they occur).

        Parameters
        ----------
        token_attrib : str
            name of the node attribute that contains the token string as its
            value (default: token).

        Yields
        -------
        result : generator of (str, unicode) or generator unicode
            a generator of (token node ID, token string) tuples if
            token_strings_only==False, a generator of token strings otherwise
        """
        if token_strings_only:
            for token_id in self.tokens:
                yield self.get_token(token_id, token_attrib)
        else:
            for token_id in self.tokens:
                yield (token_id, self.get_token(token_id, token_attrib))

    def merge_graphs(self, other_docgraph, verbose=False):
        """
        Merges another document graph into the current one, thereby adding all
        the necessary nodes and edges (with attributes, layers etc.).

        NOTE: This will only work if both graphs have exactly the same
        tokenization.
        """
        # keep track of all merged/old root nodes in case we need to
        # delete them or their attributes (e.g. 'metadata')
        if hasattr(self, 'merged_rootnodes'):
            self.merged_rootnodes.append(other_docgraph.root)
        else:
            self.merged_rootnodes = [other_docgraph.root]

        # renaming the tokens of the other graph to match this one
        rename_tokens(other_docgraph, self, verbose=verbose)
        self.add_nodes_from(other_docgraph.nodes(data=True))

        # copy token node attributes to the current namespace
        for node_id, node_attrs in other_docgraph.nodes(data=True):
            if istoken(other_docgraph, node_id) and \
                self.ns+':token' not in self.node[node_id]:
                    self.node[node_id].update({self.ns+':token': other_docgraph.get_token(node_id)})
        self.add_edges_from(other_docgraph.edges(data=True))

        # workaround for issues #89 and #96
        # copy the token node IDs / sentence node IDs from the other graph,
        # if this graph doesn't have such lists, yet
        if other_docgraph.name and not self.name:
            self.name = other_docgraph.name
        if other_docgraph.tokens and not self.tokens:
            self.tokens = other_docgraph.tokens
        if other_docgraph.sentences and not self.sentences:
            self.sentences = other_docgraph.sentences

        # there should be no dangling, unused root nodes in a merged graph
        self.merge_rootnodes(other_docgraph)

    def merge_rootnodes(self, other_docgraph):
        """
        Copy all the metadata from the root node of the other graph into this
        one. Then, move all edges belonging to the other root node to this
        one. Finally, remove the root node of the other graph from this one.
        """
        # copy metadata from other graph, cf. #136
        if 'metadata' in other_docgraph.node[other_docgraph.root]:
            other_meta = other_docgraph.node[other_docgraph.root]['metadata']
            self.node[self.root]['metadata'].update(other_meta)

        assert not other_docgraph.in_edges(other_docgraph.root), \
            "root node in graph '{}' must not have any ingoing edges".format(
                other_docgraph.name)

        for (root, target, attrs) in other_docgraph.out_edges(
            other_docgraph.root, data=True):
                self.add_edge(self.root, target, attr_dict=attrs)
        self.remove_node(other_docgraph.root)

    def add_precedence_relations(self):
        """
        add precedence relations to the document graph (i.e. an edge from the
        root node to the first token node, an edge from the first token node to
        the second one etc.)
        """
        assert len(self.tokens) > 1, \
            "There are no tokens to add precedence relations to."
        self.add_edge(self.root, self.tokens[0],
                      layers={self.ns, self.ns+':precedence'},
                      edge_type=EdgeTypes.precedence_relation)
        for i, token_node_id in enumerate(self.tokens[1:]):
            # edge from token_n to token_n+1
            self.add_edge(self.tokens[i], token_node_id,
                          layers={self.ns, self.ns+':precedence'},
                          edge_type=EdgeTypes.precedence_relation)

def rename_tokens(docgraph_with_old_names, docgraph_with_new_names, verbose=False):
    """
    Renames the tokens of a graph (``docgraph_with_old_names``) in-place,
    using the token names of another document graph
    (``docgraph_with_new_names``). Also updates the ``.tokens`` list of the old
    graph.

    This will only work, iff both graphs have the same tokenization.
    """
    old2new = create_token_mapping(docgraph_with_old_names,
                                   docgraph_with_new_names, verbose=verbose)

    # save the mappings from old to new token node IDs in the `renamed_nodes`
    # attribute of the merged graph
    if hasattr(docgraph_with_new_names, 'renamed_nodes'):
        docgraph_with_new_names.renamed_nodes.update(old2new)
    else:
        docgraph_with_new_names.renamed_nodes = old2new

    relabel_nodes(docgraph_with_old_names, old2new, copy=False)
    new_token_ids = old2new.values()

    # new_token_ids could be empty (if docgraph_with_new_names is still empty)
    if new_token_ids:
        docgraph_with_old_names.tokens = new_token_ids

def create_token_mapping(docgraph_with_old_names, docgraph_with_new_names,
                         verbose=False):
    """
    given two document graphs which annotate the same text and which use the
    same tokenization, creates a dictionary with a mapping from the token
    IDs used in the first graph to the token IDs used in the second graph.

    Parameters
    ----------
    docgraph_with_old_names : DiscourseDocumentGraph
        a document graph with token IDs that will be replaced later on
    docgraph_with_new_names : DiscourseDocumentGraph
        a document graph with token IDs that will replace the token IDs
        used in ``docgraph_with_old_names`` later on

    Returns
    -------
    old2new : dict
        maps from a token ID used in ``docgraph_with_old_names`` to the token
        ID used in ``docgraph_with_new_names`` to reference the same token
    """
    def kwic_string(docgraph, keyword_index):
        tokens = [tok for (tokid, tok) in list(docgraph.get_tokens())]
        before, keyword, after = get_kwic(tokens, keyword_index)
        return "{0} (Index: {1}): {2} [[{3}]] {4}\n".format(
            docgraph.name, keyword_index, ' '.join(before), keyword,
            ' '.join(after))

    # generators of (token ID, token) tuples
    old_token_gen = docgraph_with_old_names.get_tokens()
    new_token_gen = docgraph_with_new_names.get_tokens()

    old2new = {}
    for i, (new_tok_id, new_tok) in enumerate(new_token_gen):
        old_tok_id, old_tok = old_token_gen.next()
        if new_tok != old_tok:  # token mismatch
            if verbose:
                raise ValueError(u"Tokenization mismatch:\n{0}{1}".format(
                    kwic_string(docgraph_with_old_names, i),
                    kwic_string(docgraph_with_new_names, i)))
            raise ValueError(
                u"Tokenization mismatch: {0} ({1}) vs. {2} ({3})\n"
                "\t{4} != {5}".format(
                    docgraph_with_new_names.name, docgraph_with_new_names.ns,
                    docgraph_with_old_names.name, docgraph_with_old_names.ns,
                    new_tok, old_tok).encode('utf-8'))
        else:
            old2new[old_tok_id] = new_tok_id
    return old2new

def get_kwic(tokens, index, context_window=5):
    """
    keyword in context

    Parameters
    ----------
    tokens : list of str
        a text represented as a list of tokens
    index : int
        the index of the keyword in the token list
    context_window : int
        the number of preceding/succeding words of the keyword to be
        retrieved

    Returns
    -------
    before : list of str
        the tokens preceding the keyword
    keyword : str
        the token at the index position
    after : list of str
        the tokens succeding the keyword
    """
    text_length = len(tokens)
    start_before = max(0, index-context_window)
    end_before = max(0, index)
    before = tokens[start_before:end_before]
    start_after = min(text_length, index+1)
    end_after = min(text_length, index+context_window+1)
    after = tokens[start_after:end_after]
    return before, tokens[index], after

def get_annotation_layers(docgraph):
    """
    WARNING: this is higly inefficient!
    Fix this via Issue #36.

    Returns
    -------
    all_layers : set or dict
        the set of all annotation layers used in the given graph
    """
    node_layers = get_node_annotation_layers(docgraph)
    return node_layers.union(get_edge_annotation_layers(docgraph))

def get_top_level_layers(docgraph):
    """
    WARNING: this is higly inefficient!
    Fix this via Issue #36.

    Returns
    -------
    top_level_layers : set
        the set of all top level annotation layers used in the given graph
        (e.g. 'tiger' or 'rst', but not 'tiger:sentence:root' or 'rst:segment')
    """
    return set(layer.split(':')[0]
               for layer in get_annotation_layers(docgraph))

def get_node_annotation_layers(docgraph):
    """
    WARNING: this is higly inefficient!
    Fix this via Issue #36.

    Returns
    -------
    all_layers : set or dict
        the set of all annotation layers used for annotating nodes in the given
        graph
    """
    all_layers = set()
    for node_id, node_attribs in docgraph.nodes_iter(data=True):
        for layer in node_attribs['layers']:
            all_layers.add(layer)
    return all_layers

def get_edge_annotation_layers(docgraph):
    """
    WARNING: this is higly inefficient!
    Fix this via Issue #36.

    Returns
    -------
    all_layers : set or dict
        the set of all annotation layers used for annotating edges in the given
        graph
    """
    all_layers = set()
    for source_id, target_id, edge_attribs in docgraph.edges_iter(data=True):
        for layer in edge_attribs['layers']:
            all_layers.add(layer)
    return all_layers

def get_span_offsets(docgraph, node_id):
    """
    returns the character start and end position of the span of text that
    the given node spans or dominates.

    Returns
    -------
    offsets : tuple(int, int)
        character onset and offset of the span
    """
    try:
        span = get_span(docgraph, node_id)
        # workaround for issue #138
        # TODO: when #138 is fixed, just take the first onset / last offset
        onsets, offsets = zip(*[docgraph.get_offsets(tok_node)
                                for tok_node in span])
        return (min(onsets), max(offsets))
    except KeyError as _:
        raise KeyError("Node '{}' doesn't span any tokens.".format(node_id))

def get_span(docgraph, node_id, debug=False):
    """
    returns all the tokens that are dominated or in a span relation with
    the given node. If debug is set to True, you'll get a warning if the
    graph is cyclic.

    Returns
    -------
    span : list of str
        sorted list of token nodes (token node IDs)
    """
    if debug is True and is_directed_acyclic_graph(docgraph) is False:
        warnings.warn(
            ("Can't reliably extract span '{0}' from cyclical graph'{1}'."
            "Maximum recursion depth may be exceeded.").format(node_id,
                                                                   docgraph))
    span = []
    if docgraph.ns+':token' in docgraph.node[node_id]:
        span.append(node_id)

    for src_id, target_id, edge_attribs in docgraph.out_edges_iter(node_id,
                                                                data=True):
        if src_id == target_id:
            continue  # ignore self-loops
        # ignore pointing relations
        if edge_attribs['edge_type'] != EdgeTypes.pointing_relation:
            span.extend(get_span(docgraph, target_id))
    return sorted(span, key=natural_sort_key)

def get_text(docgraph, node_id=None):
    """
    returns the text (joined token strings) that the given node dominates
    or spans. If no node ID is given, returns the complete text of the
    document
    """
    if node_id:
        tokens = (docgraph.node[node_id][docgraph.ns+':token']
                  for node_id in get_span(docgraph, node_id))
    else:
        tokens = (docgraph.node[token_id][docgraph.ns+':token']
                  for token_id in docgraph.tokens)
    return ' '.join(tokens)

def tokens2text(docgraph, token_ids):
    """
    given a list of token node IDs, returns a their string representation
    (concatenated token strings).
    """
    return ' '.join(docgraph.node[token_id][docgraph.ns+':token']
                    for token_id in token_ids)

def istoken(docgraph, node_id, namespace=None):
    """returns true, iff the given node ID belongs to a token node.

    Parameters
    ----------
    node_id : str
        the node to be checked
    namespace : str or None
        If a namespace is given, only look for tokens in the given namespace.
        Otherwise, look for tokens in the default namespace of the given
        document graph.
    """
    if namespace is None:
        namespace = docgraph.ns
    return namespace+':token' in docgraph.node[node_id]

def is_continuous(docgraph, dominating_node):
    """return True, if the tokens dominated by the given node are all adjacent"""
    first_onset, last_offset = get_span_offsets(docgraph, dominating_node)
    span_range = xrange(first_onset, last_offset+1)

    token_offsets = (docgraph.get_offsets(tok)
                     for tok in get_span(docgraph, dominating_node))
    char_positions = set(itertools.chain.from_iterable(xrange(on, off+1)
                         for on, off in token_offsets))
    for item in span_range:
        if item not in char_positions:
            return False
    return True

def select_neighbors_by_layer(docgraph, node, layer, data=False):
    """
    Get all neighboring nodes belonging to (any of) the given layer(s),
    A neighboring node is a node that the given node connects to with an
    outgoing edge.

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        document graph from which the nodes will be extracted
    layer : str or collection of str
        name(s) of the layer(s)
    data : bool
        If True, results will include node attributes.

    Yields
    ------
    nodes : generator of str or generator of (str, dict) tuple
        If data is False (default), a generator of neighbor node IDs
        that are present in the given layer. If data is True,
        a generator of (node ID, node attrib dict) tuples.
    """
    for node_id in docgraph.neighbors_iter(node):
        node_layers = docgraph.node[node_id]['layers']
        if isinstance(layer, (str, unicode)):
            condition = layer in node_layers
        else:  # ``layer`` is a list/set/dict of layers
            condition = any(l in node_layers for l in layer)

        if condition:
            yield (node_id, docgraph.node[node_id]) if data else (node_id)

def select_neighbors_by_edge_attribute(docgraph, source,
                                       attribute=None, value=None, data=False):
    """Get all neighbors with the given edge attribute value(s)."""
    assert isinstance(docgraph, MultiGraph)
    for neighbor_id in docgraph.neighbors_iter(source):
        edges = docgraph[source][neighbor_id].values()

        if attribute is None:
            has_attrib = True # don't filter neighbors
        else:
            has_attrib = any(attribute in edge for edge in edges)

        if has_attrib:
            if value is None:
                has_value = True
            elif isinstance(value, basestring):
                has_value = any(edge.get(attribute) == value
                                for edge in edges)
            else:  # ``value`` is a list/set/dict of values
                has_value = any(edge.get(attribute) == v
                                for edge in edges
                                for v in value)

            if has_value:
                if data:
                    yield (neighbor_id, docgraph.node[neighbor_id])
                else:
                    yield neighbor_id

def select_nodes_by_layer(docgraph, layer=None, data=False):
    """
    Get all nodes belonging to (any of) the given layer(s).

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        document graph from which the nodes will be extracted
    layer : str or collection of str or None
        name(s) of the layer(s) to select nodes from. If None, returns all
        nodes
    data : bool
        If True, results will include node attributes.

    Yields
    ------
    nodes : generator of str or generator of (str, dict) tuple
        If data is False (default), a generator of node IDs that are present in
        the given layer. If data is True, a generator of (node ID, node attrib
        dict) tuples.
    """
    for node_id, node_attribs in docgraph.nodes_iter(data=True):
        if layer is None:
            condition = True # don't filter nodes
        elif isinstance(layer, (str, unicode)):
            condition = layer in node_attribs['layers']
        else:  # ``layer`` is a list/set/dict of layers
            condition = any(l in node_attribs['layers'] for l in layer)
        if condition:
            if data:
                yield (node_id, node_attribs)
            else:
                yield node_id

def select_nodes_by_attribute(docgraph, attribute=None, value=None, data=False):
    """
    Get all nodes with the given attribute (and attribute value).

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        document graph from which the nodes will be extracted
    attribute : str or None
        Name of the node attribute that all nodes must posess.
        If None, returns all nodes.
    value : str or collection of str or None
        Value of the node attribute that all nodes must posess.
        If None, returns all nodes with the given node attribute key    .
    data : bool
        If True, results will include node attributes.

    Yields
    ------
    nodes : generator of str or generator of (str, dict) tuple
        If data is False (default), a generator of node (IDs) that posess
        the given attribute. If data is True, a generator of (node ID,
        node attrib dict) tuples.
    """
    for node_id, node_attribs in docgraph.nodes_iter(data=True):
        if attribute is None:
            has_attrib = True # don't filter nodes
        else:
            has_attrib = attribute in node_attribs

        if has_attrib:
            if value is None:
                has_value = True
            elif isinstance(value, basestring):
                has_value = node_attribs.get(attribute) == value
            else:  # ``value`` is a list/set/dict of values
                has_value = any(node_attribs.get(attribute) == v for v in value)

            if has_value:
                if data:
                    yield (node_id, node_attribs)
                else:
                    yield node_id

def select_edges(docgraph, conditions, data):
    """yields all edges that meet the conditions given as eval strings"""
    for (src_id, target_id, edge_attribs) in docgraph.edges(data=True):
        # if all conditions are fulfilled
        # we need to add edge_attribs to the namespace eval is working in
        if all((eval(cond, {'edge_attribs': edge_attribs})
                for cond in conditions)):
            if data:
                yield (src_id, target_id, edge_attribs)
            else:
                yield (src_id, target_id)

def select_edges_by_attribute(docgraph, attribute=None, value=None, data=False):
    """
    get all edges with the given edge type and layer.

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        document graph from which the nodes will be extracted
    attribute : str or None
        Name of the node attribute that all nodes must posess.
        If None, returns all nodes.
    value : str or collection of str or None
        Value of the node attribute that all nodes must posess.
        If None, returns all nodes with the given node attribute key    .
    data : bool
        If True, results will include edge attributes.

    Returns
    -------
    edges : generator of str
        a container/list of edges (represented as (source node ID, target
        node ID) tuples). If data is True, edges are represented as
        (source node ID, target node ID, edge attribute dict) tuples.
    """
    if attribute:
        attrib_key_eval = "'{}' in edge_attribs".format(attribute)

        if value is not None:
            if isinstance(value, basestring):
                attrib_val_eval = \
                    "edge_attribs['{0}'] == '{1}'".format(attribute, value)
                return select_edges(
                    docgraph, data=data,
                    conditions=[attrib_key_eval, attrib_val_eval])

            else:  # ``value`` is a list/set/dict of values
                attrib_val_evals = \
                    ["edge_attribs['{0}'] == '{1}'".format(attribute, v)
                     for v in value]
                results = \
                    [select_edges(docgraph, data=data,
                                  conditions=[attrib_key_eval, val_eval])
                     for val_eval in attrib_val_evals]
                # results is a list of generators
                return itertools.chain(*results)

        else:  # yield all edges with the given attribute, regardless of value
            return select_edges(docgraph, data=data, conditions=[attrib_key_eval])

    else:  # don't filter edges at all
        return docgraph.edges_iter(data=data)

def select_edges_by(docgraph, layer=None, edge_type=None, data=False):
    """
    get all edges with the given edge type and layer.

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        document graph from which the nodes will be extracted
    layer : str
        name of the layer
    edge_type : str
        Type of the edges to be extracted (Edge types are defined in the
        Enum ``EdgeTypes``).
    data : bool
        If True, results will include edge attributes.

    Returns
    -------
    edges : generator of str
        a container/list of edges (represented as (source node ID, target
        node ID) tuples). If data is True, edges are represented as
        (source node ID, target node ID, edge attribute dict) tuples.
    """
    edge_type_eval = "edge_attribs['edge_type'] == '{}'".format(edge_type)
    layer_eval = "'{}' in edge_attribs['layers']".format(layer)

    if layer is not None:
        if edge_type is not None:
            return select_edges(docgraph, data=data,
                                conditions=[edge_type_eval, layer_eval])
        else:  # filter by layer, but not by edge type
            return select_edges(docgraph, conditions=[layer_eval], data=data)

    else:  # don't filter layers
        if edge_type is not None:  # filter by edge type, but not by layer
            return select_edges(docgraph, data=data,
                                conditions=[edge_type_eval])
        else:  # neither layer, nor edge type is filtered
            return docgraph.edges_iter(data=data)

def __walk_chain(rel_dict, src_id):
    """
    given a dict of pointing relations and a start node, this function
    will return a list of paths (each path is represented as a list of
    node IDs -- from the first node of the path to the last).

    Parameters
    ----------
    rel_dict : dict
        a dictionary mapping from an edge source node (node ID str)
        to a set of edge target nodes (node ID str)
    src_id : str

    Returns
    -------
    paths_starting_with_id : list of list of str
        each list constains a list of strings (i.e. a list of node IDs,
        which represent a chain of pointing relations)
    """
    paths_starting_with_id = []
    for target_id in rel_dict[src_id]:
        if target_id in rel_dict:
            for tail in __walk_chain(rel_dict, target_id):
                paths_starting_with_id.append([src_id] + tail)
        else:
            paths_starting_with_id.append([src_id, target_id])
    return paths_starting_with_id

def get_pointing_chains(docgraph, layer=None):
    """
    returns a list of chained pointing relations (e.g. coreference chains)
    found in the given document graph.

    Parameters
    ----------
    docgraph : DiscourseDocumentGraph
        a text with annotations, represented by a document graph
    layer : str or None
        If layer is specifid, this function will only return pointing relations
        belonging to that layer.
    """
    pointing_relations = select_edges_by(docgraph, layer=layer,
                                         edge_type=EdgeTypes.pointing_relation)

    # a markable can point to more than one antecedent, cf. Issue #40
    rel_dict = defaultdict(set)
    for src_id, target_id in pointing_relations:
        rel_dict[src_id].add(target_id)

    all_chains = [__walk_chain(rel_dict, src_id)
                  for src_id in rel_dict.iterkeys()]

    # don't return partial chains, i.e. instead of returning [a,b], [b,c] and
    # [a,b,c,d], just return [a,b,c,d]
    unique_chains = []
    for i, src_id_chains in enumerate(all_chains):
        # there will be at least one chain in this list and
        # its first element is the from ID
        src_id = src_id_chains[0][0]

        # chain lists not starting with src_id
        other_chainlists = all_chains[:i] + all_chains[i+1:]
        if not any((src_id in chain
                    for chain_list in other_chainlists
                    for chain in chain_list)):
                        unique_chains.extend(src_id_chains)
    return unique_chains

def layer2namespace(layer):
    """
    converts the name of a layer into the name of its namespace, e.g.
    'mmax:token' --> 'mmax'
    """
    return layer.split(':')[0]


text:
namespace Osmosis {
namespace Chain {
namespace Local
{

ObjectStore::ObjectStore( const boost::filesystem::path & path ) :
	_store( path ),
	_drafts( path ),
	_labels( path, _store )
{}

std::unique_ptr< ObjectStoreConnectionInterface > ObjectStore::connect()
{
	return std::unique_ptr< ObjectStoreConnectionInterface >( new Connection( _store, _drafts, _labels ) );
}

} // namespace Local
} // namespace Chain
} // namespace Osmosis


text:
const _types = require('_app/constants/action-types');

module.exports = (state = null, action) => {
    switch (action.type) {

        case _types.SEARCH_FETCHING:
            return {loading: true};

        case _types.SEARCH_FETCHING_COMPLETED:
            return {loading: false};

        case _types.SEARCH_FETCHING_FAILED:
            return {loading: false, err: action.err};

        case _types.RESET:
            return null;

        default:
            return state;

    }
};


text:
package com.amazonaws.services.storagegateway.model;

import java.io.Serializable;
import javax.annotation.Generated;

/**
 *

 * DescribeTapeRecoveryPointsOutput
 *

 *
 * @see AWS API Documentation
 */
@Generated("com.amazonaws:aws-java-sdk-code-generator")
public class DescribeTapeRecoveryPointsResult extends com.amazonaws.AmazonWebServiceResult<com.amazonaws.ResponseMetadata> implements Serializable, Cloneable {

    private String gatewayARN;
    /**
     *

     * An array of TapeRecoveryPointInfos that are available for the specified gateway.
     *

     */
    private com.amazonaws.internal.SdkInternalList<TapeRecoveryPointInfo> tapeRecoveryPointInfos;
    /**
     *

     * An opaque string that indicates the position at which the virtual tape recovery points that were listed for
     * description ended.
     *

     *

     * Use this marker in your next request to list the next set of virtual tape recovery points in the list. If there
     * are no more recovery points to describe, this field does not appear in the response.
     *

     */
    private String marker;

    /**
     * @param gatewayARN
     */

    public void setGatewayARN(String gatewayARN) {
        this.gatewayARN = gatewayARN;
    }

    /**
     * @return
     */

    public String getGatewayARN() {
        return this.gatewayARN;
    }

    /**
     * @param gatewayARN
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DescribeTapeRecoveryPointsResult withGatewayARN(String gatewayARN) {
        setGatewayARN(gatewayARN);
        return this;
    }

    /**
     *

     * An array of TapeRecoveryPointInfos that are available for the specified gateway.
     *

     *
     * @return An array of TapeRecoveryPointInfos that are available for the specified gateway.
     */

    public java.util.List<TapeRecoveryPointInfo> getTapeRecoveryPointInfos() {
        if (tapeRecoveryPointInfos == null) {
            tapeRecoveryPointInfos = new com.amazonaws.internal.SdkInternalList<TapeRecoveryPointInfo>();
        }
        return tapeRecoveryPointInfos;
    }

    /**
     *

     * An array of TapeRecoveryPointInfos that are available for the specified gateway.
     *

     *
     * @param tapeRecoveryPointInfos
     *        An array of TapeRecoveryPointInfos that are available for the specified gateway.
     */

    public void setTapeRecoveryPointInfos(java.util.Collection<TapeRecoveryPointInfo> tapeRecoveryPointInfos) {
        if (tapeRecoveryPointInfos == null) {
            this.tapeRecoveryPointInfos = null;
            return;
        }

        this.tapeRecoveryPointInfos = new com.amazonaws.internal.SdkInternalList<TapeRecoveryPointInfo>(tapeRecoveryPointInfos);
    }

    /**
     *

     * An array of TapeRecoveryPointInfos that are available for the specified gateway.
     *

     *

     * NOTE: This method appends the values to the existing list (if any). Use
     * {@link #setTapeRecoveryPointInfos(java.util.Collection)} or
     * {@link #withTapeRecoveryPointInfos(java.util.Collection)} if you want to override the existing values.
     *

     *
     * @param tapeRecoveryPointInfos
     *        An array of TapeRecoveryPointInfos that are available for the specified gateway.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DescribeTapeRecoveryPointsResult withTapeRecoveryPointInfos(TapeRecoveryPointInfo... tapeRecoveryPointInfos) {
        if (this.tapeRecoveryPointInfos == null) {
            setTapeRecoveryPointInfos(new com.amazonaws.internal.SdkInternalList<TapeRecoveryPointInfo>(tapeRecoveryPointInfos.length));
        }
        for (TapeRecoveryPointInfo ele : tapeRecoveryPointInfos) {
            this.tapeRecoveryPointInfos.add(ele);
        }
        return this;
    }

    /**
     *

     * An array of TapeRecoveryPointInfos that are available for the specified gateway.
     *

     *
     * @param tapeRecoveryPointInfos
     *        An array of TapeRecoveryPointInfos that are available for the specified gateway.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DescribeTapeRecoveryPointsResult withTapeRecoveryPointInfos(java.util.Collection<TapeRecoveryPointInfo> tapeRecoveryPointInfos) {
        setTapeRecoveryPointInfos(tapeRecoveryPointInfos);
        return this;
    }

    /**
     *

     * An opaque string that indicates the position at which the virtual tape recovery points that were listed for
     * description ended.
     *

     *

     * Use this marker in your next request to list the next set of virtual tape recovery points in the list. If there
     * are no more recovery points to describe, this field does not appear in the response.
     *

     *
     * @param marker
     *        An opaque string that indicates the position at which the virtual tape recovery points that were listed
     *        for description ended.

     *

     *        Use this marker in your next request to list the next set of virtual tape recovery points in the list. If
     *        there are no more recovery points to describe, this field does not appear in the response.
     */

    public void setMarker(String marker) {
        this.marker = marker;
    }

    /**
     *

     * An opaque string that indicates the position at which the virtual tape recovery points that were listed for
     * description ended.
     *

     *

     * Use this marker in your next request to list the next set of virtual tape recovery points in the list. If there
     * are no more recovery points to describe, this field does not appear in the response.
     *

     *
     * @return An opaque string that indicates the position at which the virtual tape recovery points that were listed
     *         for description ended.

     *

     *         Use this marker in your next request to list the next set of virtual tape recovery points in the list. If
     *         there are no more recovery points to describe, this field does not appear in the response.
     */

    public String getMarker() {
        return this.marker;
    }

    /**
     *

     * An opaque string that indicates the position at which the virtual tape recovery points that were listed for
     * description ended.
     *

     *

     * Use this marker in your next request to list the next set of virtual tape recovery points in the list. If there
     * are no more recovery points to describe, this field does not appear in the response.
     *

     *
     * @param marker
     *        An opaque string that indicates the position at which the virtual tape recovery points that were listed
     *        for description ended.

     *

     *        Use this marker in your next request to list the next set of virtual tape recovery points in the list. If
     *        there are no more recovery points to describe, this field does not appear in the response.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DescribeTapeRecoveryPointsResult withMarker(String marker) {
        setMarker(marker);
        return this;
    }

    /**
     * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be
     * redacted from this string using a placeholder value.
     *
     * @return A string representation of this object.
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        if (getGatewayARN() != null)
            sb.append("GatewayARN: ").append(getGatewayARN()).append(",");
        if (getTapeRecoveryPointInfos() != null)
            sb.append("TapeRecoveryPointInfos: ").append(getTapeRecoveryPointInfos()).append(",");
        if (getMarker() != null)
            sb.append("Marker: ").append(getMarker());
        sb.append("}");
        return sb.toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;

        if (obj instanceof DescribeTapeRecoveryPointsResult == false)
            return false;
        DescribeTapeRecoveryPointsResult other = (DescribeTapeRecoveryPointsResult) obj;
        if (other.getGatewayARN() == null ^ this.getGatewayARN() == null)
            return false;
        if (other.getGatewayARN() != null && other.getGatewayARN().equals(this.getGatewayARN()) == false)
            return false;
        if (other.getTapeRecoveryPointInfos() == null ^ this.getTapeRecoveryPointInfos() == null)
            return false;
        if (other.getTapeRecoveryPointInfos() != null && other.getTapeRecoveryPointInfos().equals(this.getTapeRecoveryPointInfos()) == false)
            return false;
        if (other.getMarker() == null ^ this.getMarker() == null)
            return false;
        if (other.getMarker() != null && other.getMarker().equals(this.getMarker()) == false)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int hashCode = 1;

        hashCode = prime * hashCode + ((getGatewayARN() == null) ? 0 : getGatewayARN().hashCode());
        hashCode = prime * hashCode + ((getTapeRecoveryPointInfos() == null) ? 0 : getTapeRecoveryPointInfos().hashCode());
        hashCode = prime * hashCode + ((getMarker() == null) ? 0 : getMarker().hashCode());
        return hashCode;
    }

    @Override
    public DescribeTapeRecoveryPointsResult clone() {
        try {
            return (DescribeTapeRecoveryPointsResult) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone() " + "even though we're Cloneable!", e);
        }
    }

}


text:
from: "20:00"
to: "24:00"
break: true
title: Afterparty by EPAM
sponsor:
location:
address:
url:
speaker:

details: Join us for drinks, games and hacking at Extra located near the venue
---


text:
Jeg kan hjælpe dig videre

Jeg er helt klar til at blive en brik i dit fremtidige liv.

                Start allerede i dag


text:
angular.module('AppMain')
        .factory('validation', function ($rootScope) {
            return {
            };
        });


text:
class Quiz
  extend ActiveModel::Naming

  attr_reader :questions

  OPTIONS_COUNT = 5
  MAX_QUESTIONS_COUNT = 50

  # Converts the [Array] of `term` and `definition` pairs into a [Quiz]
  # There should be at least `OPTIONS_COUNT` + 1 concepts in order to make a quiz (6 concepts)
  #
  # @param concepts [Array] An array of `term` and `definition` pairs.
  # @return quiz [Quiz]
  #
  # @example
  #   concepts = [{ term: "Apple", definition: "A red fruit" }, { term: "Car", definition: "A 4 wheeled motor vehicle" }]
  #
  def self.build_from_concepts(concepts)
    quiz = new
    concepts = concepts.sample(MAX_QUESTIONS_COUNT)
    concepts.each_with_index do |concept, index|
      question_is_a_term = rand(2).zero?
      text = question_is_a_term ? concept[:term] : concept[:definition]
      correct_answer = question_is_a_term ? concept[:definition] : concept[:term]
      option_texts = option_texts(concepts, question_is_a_term, correct_answer)
      options = create_options_from_option_texts(option_texts, correct_answer)
      quiz.add_question({ number: index + 1, text: text, correct_answer: correct_answer, options: options })
    end
    quiz
  end

  # Take JSON input of quiz data and create a quiz object.
  # This is used to recreate a quiz with user answers and results
  # (with the same order of questions and optoions, no randomness)
  #
  # @param quiz_hash [String, Hash] The JSON or Hash of `Quiz` properties.
  # @param user_answers [Hash] The user answers `params` from the controller.
  # @return [Quiz]
  #
  # @example
  #   options = [ { text: "Apple", letter: 'A', is_correct_answer: true, is_selected: false }, ... ]
  #   quiz_hash  # => { text: "Red Fruit?", number: 1, correct_answer: "Apple", options: options }
  #   user_answers  # => {"1": "Apple", "2": "A 4 wheeled motor vehicle"}
  #
  def self.build_from_quiz_hash(quiz_hash, user_answers)
    user_answers = user_answers.with_indifferent_access
    # FIXME: This method should be able to take either a JSON or an Array of Hashes without the need for rescue
    quiz_hash = JSON.parse(quiz_hash).with_indifferent_access rescue quiz_hash
    quiz = new
    quiz_hash[:questions].each do |question|
      quiz.add_question(question.except(:options)).build_options_from_hash(question[:options], user_answers)
    end
    quiz
  end

  def initialize
    @questions ||= []
  end

  def to_json
    { questions: questions }.to_json
  end

  def add_question(input)
    Quiz::Question.new(input.symbolize_keys).tap { |question| @questions << question }
  end

  def correct_answers
    @correct_answers ||= questions.select { |question| question.answered_correctly? }
  end

  def incorrect_answers
    @incorrect_answers ||= questions.select { |question| question.answered_incorrectly? }
  end

  def unanswerd_questions
    @unanswerd_questions ||= questions.select { |question| !question.answered? }
  end

  def percent_correct
    (correct_answers.count * 100 / questions.count).floor
  end

  #
  # Private
  #

  private

  # Get random options as text and exclude the correct answer
  #
  # @param concepts [Array] The list of `term` and `definition` pairs
  # @param question_is_a_term [Boolean] Is the question a `term` or a `definition`?
  #   This means that the options will have to be the oposite
  # @param correct_answer [String]
  # @return [Array<String>] List of options as text
  # @!visibility private
  #
  def self.option_texts(concepts, question_is_a_term, correct_answer)
    answer_type = question_is_a_term ? :definition : :term
    concepts.map { |item| item[answer_type] }.reject { |item| item  == correct_answer }.sample(OPTIONS_COUNT)
  end

  # Randomly add "None of the above." as the last option then randomly set one of the options as the correct option.
  #
  # @param option_texts [Array<String>] Strings that will become the text for the `Option` objects.
  # @param correct_answer [String] The correct answer (and therefore the correct option to select).
  # @return option_texts [Array<String>] List of options as text
  # @!visibility private
  #
  def self.create_options_from_option_texts(option_texts, correct_answer)
    none_is_an_option = rand(2).zero?
    option_texts[-1] = I18n.t("app.none_of_the_above") if none_is_an_option
    random_index = rand(0..option_texts.count - 1)
    option_texts[random_index] = correct_answer unless none_is_an_option && rand(3).zero?
    option_texts
  end
end


text:
package org.apache.parquet.avro;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.util.Utf8;
import org.apache.parquet.column.Dictionary;
import org.apache.parquet.io.ParquetDecodingException;
import org.apache.parquet.io.api.Binary;
import org.apache.parquet.io.api.GroupConverter;
import org.apache.parquet.io.api.PrimitiveConverter;
import org.apache.parquet.schema.PrimitiveStringifier;
import org.apache.parquet.schema.PrimitiveType;

public class AvroConverters {

  public abstract static class AvroGroupConverter extends GroupConverter {
    protected final ParentValueContainer parent;

    public AvroGroupConverter(ParentValueContainer parent) {
      this.parent = parent;
    }
  }

  static class AvroPrimitiveConverter extends PrimitiveConverter {
    protected final ParentValueContainer parent;

    public AvroPrimitiveConverter(ParentValueContainer parent) {
      this.parent = parent;
    }
  }

  abstract static class BinaryConverter<T> extends AvroPrimitiveConverter {
    private T[] dict = null;

    public BinaryConverter(ParentValueContainer parent) {
      super(parent);
    }

    public abstract T convert(Binary binary);

    @Override
    public void addBinary(Binary value) {
      parent.add(convert(value));
    }

    @Override
    public boolean hasDictionarySupport() {
      return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void setDictionary(Dictionary dictionary) {
      dict = (T[]) new Object[dictionary.getMaxId() + 1];
      for (int i = 0; i <= dictionary.getMaxId(); i++) {
        dict[i] = convert(dictionary.decodeToBinary(i));
      }
    }

    public T prepareDictionaryValue(T value) {
      return value;
    }

    @Override
    public void addValueFromDictionary(int dictionaryId) {
      parent.add(prepareDictionaryValue(dict[dictionaryId]));
    }
  }

  static final class FieldByteConverter extends AvroPrimitiveConverter {
    public FieldByteConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public void addInt(int value) {
      parent.addByte((byte) value);
    }
  }

  static final class FieldShortConverter extends AvroPrimitiveConverter {
    public FieldShortConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public void addInt(int value) {
      parent.addShort((short) value);
    }
  }

  static final class FieldCharConverter extends AvroPrimitiveConverter {
    public FieldCharConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public void addInt(int value) {
      parent.addChar((char) value);
    }
  }

  static final class FieldBooleanConverter extends AvroPrimitiveConverter {
    public FieldBooleanConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    final public void addBoolean(boolean value) {
      parent.addBoolean(value);
    }
  }

  static final class FieldIntegerConverter extends AvroPrimitiveConverter {
    public FieldIntegerConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    final public void addInt(int value) {
      parent.addInt(value);
    }
  }

  static final class FieldLongConverter extends AvroPrimitiveConverter {
    public FieldLongConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    final public void addInt(int value) {
      parent.addLong((long) value);
    }

    @Override
    final public void addLong(long value) {
      parent.addLong(value);
    }
  }

  static final class FieldFloatConverter extends AvroPrimitiveConverter {
    public FieldFloatConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    final public void addInt(int value) {
      parent.addFloat((float) value);
    }

    @Override
    final public void addLong(long value) {
      parent.addFloat((float) value);
    }

    @Override
    final public void addFloat(float value) {
      parent.addFloat(value);
    }
  }

  static final class FieldDoubleConverter extends AvroPrimitiveConverter {
    public FieldDoubleConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    final public void addInt(int value) {
      parent.addDouble((double) value);
    }

    @Override
    final public void addLong(long value) {
      parent.addDouble((double) value);
    }

    @Override
    final public void addFloat(float value) {
      parent.addDouble((double) value);
    }

    @Override
    final public void addDouble(double value) {
      parent.addDouble(value);
    }
  }

  static final class FieldByteArrayConverter extends BinaryConverter<byte[]> {
    public FieldByteArrayConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public byte[] convert(Binary binary) {
      return binary.getBytes();
    }
  }

  static final class FieldByteBufferConverter extends BinaryConverter<ByteBuffer> {
    public FieldByteBufferConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public ByteBuffer convert(Binary binary) {
      return ByteBuffer.wrap(binary.getBytes());
    }

    @Override
    public ByteBuffer prepareDictionaryValue(ByteBuffer value) {
      return value.duplicate();
    }
  }

  static final class FieldStringConverter extends BinaryConverter<String> {
    public FieldStringConverter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public String convert(Binary binary) {
      return binary.toStringUsingUTF8();
    }
  }

  static final class FieldUTF8Converter extends BinaryConverter<Utf8> {
    public FieldUTF8Converter(ParentValueContainer parent) {
      super(parent);
    }

    @Override
    public Utf8 convert(Binary binary) {
      return new Utf8(binary.getBytes());
    }
  }

  static final class FieldStringableConverter extends BinaryConverter<Object> {
    private final String stringableName;
    private final Constructor<?> ctor;

    public FieldStringableConverter(ParentValueContainer parent,
                                    Class<?> stringableClass) {
      super(parent);
      stringableName = stringableClass.getName();
      try {
        this.ctor = stringableClass.getConstructor(String.class);
      } catch (NoSuchMethodException e) {
        throw new ParquetDecodingException(
            "Unable to get String constructor for " + stringableName, e);
      }
    }

    @Override
    public Object convert(Binary binary) {
      try {
        return ctor.newInstance(binary.toStringUsingUTF8());
      } catch (InstantiationException | IllegalAccessException
          | InvocationTargetException e) {
        throw new ParquetDecodingException(
            "Cannot convert binary to " + stringableName, e);
      }
    }
  }

  static final class FieldEnumConverter extends BinaryConverter<Object> {
    private final Schema schema;
    private final GenericData model;

    public FieldEnumConverter(ParentValueContainer parent, Schema enumSchema,
                              GenericData model) {
      super(parent);
      this.schema = enumSchema;
      this.model = model;
    }

    @Override
    public Object convert(Binary binary) {
      return model.createEnum(binary.toStringUsingUTF8(), schema);
    }
  }

  static final class FieldFixedConverter extends BinaryConverter<Object> {
    private final Schema schema;
    private final GenericData model;

    public FieldFixedConverter(ParentValueContainer parent, Schema avroSchema,
                               GenericData model) {
      super(parent);
      this.schema = avroSchema;
      this.model = model;
    }

    @Override
    public Object convert(Binary binary) {
      return model.createFixed(null /* reuse */, binary.getBytes(), schema);
    }
  }

  static final class FieldUUIDConverter extends BinaryConverter<String> {
    private final PrimitiveStringifier stringifier;

    public FieldUUIDConverter(ParentValueContainer parent, PrimitiveType type) {
      super(parent);
      stringifier = type.stringifier();
    }

    @Override
    public String convert(Binary binary) {
      return stringifier.stringify(binary);
    }
  }
}


text:
layout: post
title: Spring Boot系列之十 自定义banner和getExitCode
date: 2016-10-28 11:12:00 +0800
categories: Spring-Boot
tag: Spring Boot
keywords: Spring Boot,自定义banner,getExitCode
---

* content
{:toc}

简介
====
本文主要就说下在Spring Boot项目启动时控制台打印的banner图标如何自定义以及Spring Context生命周期结束时执行的`ExitCodeGenerator`

自定义banner
=====

* 链接

国外有一个专门用来生成banner的网址:[banner](http://patorjk.com/software/taag),打开这个网址,生成你想要的字儿.

![](https://github.com/sunshineasbefore/resource/blob/master/bannertxt.png?raw=true)

生成时,我们可以选择自己喜欢的字体等信息.

完成后,选择`select&copy`复制到`banner.txt`文件并将其放到`src/main/resources/`目录下,重新启动应用程序.

![](https://github.com/sunshineasbefore/resource/blob/master/bannerview.png?raw=true)

额,名字太长也是种病啊`/ch`.

ExitCodeGenerator
================
生命周期结束时,会执行`ExitCodeGenerator`接口的`getExitCode()`.这个接口也只有这一个方法.

这个接口让我们在`SpringApplication`结束时,可以做一些我们自己想做的,或者必须要去做的工作,比如说数据库链接的关闭,IO流的关闭等等.当然前提时我们需要手动调用`SpringApplication`的结束操作.

直接杀掉进程(kill -9 pid)的话是不会执行的,你想想,进程都死了,还执行个啥? kill 的级别不记得了,应该还是有能够执行的.

## 示例

* ExitCodeConfig

      package cn.veryjava;

      import org.springframework.boot.ExitCodeGenerator;
      import org.springframework.stereotype.Component;

      @Component
      public class ExitCodeConfig implements ExitCodeGenerator {
        @Override
        public int getExitCode() {
          // 自定义程序结束时返回的退出码
          System.out.println("// the application exited;");
          return 1024;
        }
      }

* BannerAndLifeApplication

    这个,我懒,这个主main类,我写了N多注解...

      package cn.veryjava;

      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.support.ApplicationObjectSupport;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.ResponseBody;

      @SpringBootApplication
      @Controller
      @Configuration
      public class BannerAndLifeApplication extends ApplicationObjectSupport {

        @Autowired
        private ExitCodeConfig exitCodeConfig;

        public static void main(String[] args) {
          SpringApplication.run(BannerAndLifeApplication.class, args);
        }

        @RequestMapping("/exit")
        @ResponseBody
        public String exit() {
          SpringApplication.exit(super.getApplicationContext(), exitCodeConfig);
          return "ok";
        }

      }

* 测试

  启动完成,打开浏览器输入`http://localhost:8080/exit`或者`curl http://localhost:8080/exit` 执行SpringApplication的关闭操作.

  查看控制台输出:`// the application exited;`

代码
=====

> [Spring Boot 自定义banner和getExitCode](https://github.com/sunshineasbefore/veryjava.spring.boot/tree/master/bannerandlife)


text:
export default {
	nonSemVerExperiments: {
		unsupported: true,
	},
};