text:
sap.ui.require([
	"jquery.sap.global",
	"sap/ui/model/odata/v4/lib/_MetadataConverter",
	"sap/ui/model/odata/v4/lib/_V2MetadataConverter",
	"sap/ui/model/odata/v4/lib/_V4MetadataConverter",
	"jquery.sap.xml" // unused, needed to have jQuery.sap.parseXML
], function (jQuery, _MetadataConverter, _V2MetadataConverter, _V4MetadataConverter) {
	/*global QUnit, sinon */
	/*eslint no-warning-comments: 0 */
	"use strict";

	var sV2Start = '<edmx:Edmx Version="1.0" xmlns="http://schemas.microsoft.com/ado/2008/09/edm"'
			+ ' xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"'
			+ ' xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">'
			+ '<edmx:DataServices m:DataServiceVersion="2.0">',
		sV4Start = '<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"'
			+ ' xmlns="http://docs.oasis-open.org/odata/ns/edm"><edmx:DataServices>',
		sEnd = "</edmx:DataServices></edmx:Edmx>";

	/**
	 * Creates a DOM document from the given string.
	 * @param {object} assert the assertions
	 * @param {string} sXml the XML as string
	 * @returns {Document} the DOM document
	 */
	function xml(assert, sXml) {
		var oDocument = jQuery.sap.parseXML(sXml);
		assert.strictEqual(oDocument.parseError.errorCode, 0, "XML parsed correctly");
		return oDocument;
	}
	// TODO how to avoid duplication of this test method?

	/**
	 * Tests the conversion of the given XML snippet of a constant/dynamic expression below an
	 * Annotation element. If the expression contains a Path element, a second test is performed
	 * with the Path element replaced by an expression. By this recursive expressions are tested
	 * automatically.
	 *
	 * @param {object} assert
	 *   QUnit's assert
	 * @param {string} sXmlSnippet
	 *   the XML snippet; it will be inserted below an Annotation element
	 * @param {string} sODataVersion
	 *   the OData version to use for the test
	 * @param {any} vExpected
	 *   the expected value for the annotation
	 */
	function testExpression(assert, sXmlSnippet, vExpected, sODataVersion) {
		var aMatches, sPath;

		function convert(oConverter, sXml) {
			var oResult = oConverter.convertXMLMetadata(xml(assert, sXml));
			assert.deepEqual(oResult["foo."].$Annotations["foo.Bar"]["@foo.Term"], vExpected,
				sXml);
		}

		function localTest() {
			if (!sODataVersion || sODataVersion === "2.0") {
				convert(_V2MetadataConverter, sV2Start + sXmlSnippet + sEnd);
			}
			if (!sODataVersion || sODataVersion === "4.0") {
				convert(_V4MetadataConverter, sV4Start + sXmlSnippet + sEnd);
			}
		}

		sXmlSnippet = '\
			<Schema Namespace="foo" Alias="f">\
				<Annotations Target="foo.Bar">\
					<Annotation Term="foo.Term">' + sXmlSnippet + '</Annotation>\
				</Annotations>\
			</Schema>';

		localTest();

		// Rewrite sXmlSnippet and vExpectedValue so that the (first) Path is converted to a
		// (rather stupid) If and thus create a recursive expression.
		aMatches = /<Path>(.*?)<\/Path>/.exec(sXmlSnippet);
		if (aMatches) {
			sPath = aMatches[1];
			sXmlSnippet = sXmlSnippet.replace("<Path>" + sPath + "</Path>",
				"<If><Bool>true</Bool><Path>" + sPath + "</Path><Null/></If>");
			sPath = '{"$Path":"' + sPath.replace(/f\./g, "foo.") + '"}';
			vExpected = JSON.parse(JSON.stringify(vExpected)
				.replace(sPath, '{"$If":[true,' + sPath + ',null]}'));
			localTest();
		}
	}

	//*********************************************************************************************
	QUnit.module("sap.ui.model.odata.v4.lib._MetadataConverter", {
		beforeEach : function () {
			this.oSandbox = sinon.sandbox.create();
			this.oLogMock = this.oSandbox.mock(jQuery.sap.log);
			this.oLogMock.expects("warning").never();
			this.oLogMock.expects("error").never();
		},

		afterEach : function () {
			this.oSandbox.verifyAndRestore();
		}
	});

	//*********************************************************************************************
	QUnit.test("traverse", function (assert) {
		var oXML = xml(assert, "<foo><!-- a comment -->text<bar/>more text <ignore/><bar/>"
				+ "<bar><included1/><included2/></bar>"
				+ "\n<bar><innerBar/><innerBar/><innerBar2/></bar></foo>"),
			oAggregate = {
				bar : 0,
				innerBar : 0,
				innerBar2 : 0,
				included1 : 0,
				included2 : 0
			},
			oInclude1Config = {
				"included1" : {
					__processor : processor.bind(null, "included1")
				}
			},
			oInclude2Config = {
				"included2" : {
					__processor : processor.bind(null, "included2")
				}
			},
			oSchemaConfig = {
				"bar" : {
					__processor : processor.bind(null, "bar"),
					__include : [oInclude1Config, oInclude2Config],
					"innerBar" : {
						__processor : processor.bind(null, "innerBar")
					},
					"innerBar2" : {
						__processor : processor.bind(null, "innerBar2")
					}
				}
			};

		function processor(sExpectedName, oElement, oMyAggregate) {
			assert.strictEqual(oElement.nodeType, 1, "is an Element");
			assert.strictEqual(oElement.localName, sExpectedName);
			assert.strictEqual(oMyAggregate, oAggregate);
			oMyAggregate[sExpectedName]++;
		}

		_MetadataConverter.traverse(oXML.documentElement, oAggregate, oSchemaConfig);
		assert.strictEqual(oAggregate.bar, 4);
		assert.strictEqual(oAggregate.innerBar, 2);
		assert.strictEqual(oAggregate.innerBar2, 1);
		assert.strictEqual(oAggregate.included1, 1);
		assert.strictEqual(oAggregate.included2, 1);
	});

	//*********************************************************************************************
	QUnit.test("traverse: __postProcessor", function (assert) {
		var oXML = xml(assert, "<And><Bool>true</Bool><Bool>false</Bool></And>"),
			oResult = _MetadataConverter.traverse(oXML.documentElement, {}, {
				__postProcessor : function (oElement, aResults) {
					return {$And : aResults};
				},
				"Bool" : {
					__postProcessor : function (oElement, aResults) {
						assert.deepEqual(aResults, []);
						return oElement.childNodes[0].nodeValue === "true";
					}
				}
			});
			assert.deepEqual(oResult, {$And : [true, false]});
	});

	//*********************************************************************************************
	QUnit.test("resolveAlias", function (assert) {
		var oAggregate = {
				aliases : {
					"display" : "org.example.vocabularies.display."
				}
			};

		assert.strictEqual(_MetadataConverter.resolveAlias("", oAggregate), "");
		assert.strictEqual(_MetadataConverter.resolveAlias("display.Foo", oAggregate),
			"org.example.vocabularies.display.Foo");
		assert.strictEqual(_MetadataConverter.resolveAlias("display.bar.Foo", oAggregate),
			"display.bar.Foo");
		assert.strictEqual(_MetadataConverter.resolveAlias("bar.Foo", oAggregate), "bar.Foo");
		assert.strictEqual(_MetadataConverter.resolveAlias("Foo", oAggregate), "Foo");
	});

	//*********************************************************************************************
	QUnit.test("resolveAliasInPath", function (assert) {
		var oAggregate = {},
			oMock = this.mock(_MetadataConverter);

			function localTest(sPath, sExpected) {
				assert.strictEqual(_MetadataConverter.resolveAliasInPath(sPath, oAggregate),
					sExpected || sPath);
			}

			oMock.expects("resolveAlias").never();

			localTest("Employees");
			localTest("Employees/Team");

			oMock.expects("resolveAlias")
				.withExactArgs("f.Some", sinon.match.same(oAggregate)).returns("foo.Some");
			oMock.expects("resolveAlias")
				.withExactArgs("f.Random", sinon.match.same(oAggregate)).returns("foo.Random");
			oMock.expects("resolveAlias")
				.withExactArgs("f.Path", sinon.match.same(oAggregate)).returns("foo.Path");
			localTest("f.Some/f.Random/f.Path", "foo.Some/foo.Random/foo.Path");

			oMock.expects("resolveAlias")
				.withExactArgs("f.Path", sinon.match.same(oAggregate)).returns("foo.Path");
			oMock.expects("resolveAlias")
				.withExactArgs("f.Term", sinon.match.same(oAggregate)).returns("foo.Term");
			localTest("f.Path@f.Term", "foo.Path@foo.Term");

			oMock.expects("resolveAlias")
				.withExactArgs("f.Path", sinon.match.same(oAggregate)).returns("foo.Path");
			oMock.expects("resolveAlias")
				.withExactArgs("", sinon.match.same(oAggregate)).returns("");
			oMock.expects("resolveAlias")
				.withExactArgs("f.Term", sinon.match.same(oAggregate)).returns("foo.Term");
			localTest("f.Path/@f.Term", "foo.Path/@foo.Term");
	});

	//*********************************************************************************************
	QUnit.test("annotations: leaf elements", function (assert) {
		testExpression(assert, '<String>foo\nbar</String>', "foo\nbar");
		testExpression(assert, '<String>foo<!-- bar --></String>', "foo");
		testExpression(assert, '<String><!-- foo -->bar</String>', "bar");
		testExpression(assert, '<String>foo<!-- bar -->baz</String>', "foobaz");

		testExpression(assert, '<Binary>T0RhdGE</Binary>', {"$Binary": "T0RhdGE"});
		testExpression(assert, '<Bool>false</Bool>', false);
		testExpression(assert, '<Date>2015-01-01</Date>', {"$Date" : "2015-01-01"});
		testExpression(assert, '<DateTimeOffset>2000-01-01T16:00:00.000-09:00</DateTimeOffset>',
			{"$DateTimeOffset" : "2000-01-01T16:00:00.000-09:00"});
		testExpression(assert, '<Decimal>3.14</Decimal>', {"$Decimal" : "3.14"});
		testExpression(assert, '<Duration>P11D23H59M59S</Duration>',
			{"$Duration" : "P11D23H59M59S"});
		testExpression(assert, '<EnumMember> foo.Enum/Member1  foo.Enum/Member2 </EnumMember>',
			{"$EnumMember" : "foo.Enum/Member1 foo.Enum/Member2"});
		testExpression(assert, '<Float>2.718</Float>', 2.718);
		testExpression(assert, '<Float>NaN</Float>', {"$Float" : "NaN"});
		testExpression(assert, '<Float>-INF</Float>', {"$Float" : "-INF"});
		testExpression(assert, '<Float>INF</Float>', {"$Float" : "INF"});
		testExpression(assert, '<Guid>21EC2020-3AEA-1069-A2DD-08002B30309D</Guid>',
			{"$Guid" : "21EC2020-3AEA-1069-A2DD-08002B30309D"});
		testExpression(assert, '<Int>42</Int>', 42);
		testExpression(assert, '<Int>9007199254740991</Int>', 9007199254740991);
		testExpression(assert, '<Int>9007199254740992</Int>', {"$Int" : "9007199254740992"});
		testExpression(assert, '<TimeOfDay>21:45:00</TimeOfDay>', {"$TimeOfDay" : "21:45:00"});
		testExpression(assert, '<AnnotationPath>Path/f.Bar@f.Term</AnnotationPath>',
			{"$AnnotationPath" : "Path/foo.Bar@foo.Term"});
		testExpression(assert,
			'<NavigationPropertyPath>Path/f.Bar/f.Baz</NavigationPropertyPath>',
			{"$NavigationPropertyPath" : "Path/foo.Bar/foo.Baz"});
		testExpression(assert, '<Path>Path/f.Bar/f.Baz</Path>', {"$Path" : "Path/foo.Bar/foo.Baz"});
		testExpression(assert, '<PropertyPath>Path/f.Bar/f.Baz</PropertyPath>',
			{"$PropertyPath" : "Path/foo.Bar/foo.Baz"});
		testExpression(assert, '<Null/>', null);
		testExpression(assert,
			'<LabeledElementReference>f.LabeledElement</LabeledElementReference>',
			{"$LabeledElementReference" : "foo.LabeledElement"});
	});

	//*********************************************************************************************
	QUnit.test("annotations: operators", function (assert) {
		testExpression(assert, '<And><Path>IsMale</Path><Path>IsMarried</Path></And>',
			{"$And" : [{"$Path" : "IsMale"}, {"$Path" : "IsMarried"}]});
		testExpression(assert, '<Or><Path>IsMale</Path><Path>IsMarried</Path></Or>',
			{"$Or" : [{"$Path" : "IsMale"}, {"$Path" : "IsMarried"}]});
		testExpression(assert, '<Not><Path>IsMale</Path></Not>', {"$Not" : {"$Path" : "IsMale"}});
		testExpression(assert, '<Eq><Null/><Path>IsMale</Path></Eq>',
			{"$Eq" : [null, {"$Path" : "IsMale"}]});
		testExpression(assert, '<Ne><Null/><Path>IsMale</Path></Ne>',
			{"$Ne" : [null, {"$Path" : "IsMale"}]});
		testExpression(assert, '<Gt><Path>Price</Path><Int>20</Int></Gt>',
			{"$Gt" : [{"$Path" : "Price"}, 20]});
		testExpression(assert, '<Ge><Path>Price</Path><Int>20</Int></Ge>',
			{"$Ge" : [{"$Path" : "Price"}, 20]});
		testExpression(assert, '<Le><Path>Price</Path><Int>20</Int></Le>',
			{"$Le" : [{"$Path" : "Price"}, 20]});
		testExpression(assert, '<Lt><Path>Price</Path><Int>20</Int></Lt>',
			{"$Lt" : [{"$Path" : "Price"}, 20]});
		testExpression(assert,
			'<If><Path>IsFemale</Path><String>Female</String><String>Male</String></If>',
			{"$If" : [{"$Path" : "IsFemale"}, "Female", "Male"]});
	});

	//*********************************************************************************************
	QUnit.test("annotations: Apply", function (assert) {
		testExpression(assert, '<Apply Function="f.Bar"/>',
			{"$Apply" : [], "$Function" : "foo.Bar"});
		testExpression(assert, '<Apply Function="odata.concat"><String>Product: </String>'
			+ '<Path>ProductName</Path></Apply>',
			{"$Apply" : ["Product: ", {"$Path" : "ProductName"}], "$Function" : "odata.concat"});
	});

	//*********************************************************************************************
	QUnit.test("annotations: Cast and IsOf", function (assert) {
		testExpression(assert, '<Cast Type="Collection(f.Type)"><Path>Average</Path></Cast>', {
			"$Cast" : {"$Path" : "Average"},
			"$Type" : "foo.Type",
			"$isCollection" : true
		});
		testExpression(assert, '<Cast Type="Edm.Decimal" MaxLength="10" Precision="8" Scale="2">'
			+ '<Float>42</Float></Cast>', {
			"$Cast" : 42,
			"$Type" : "Edm.Decimal",
			"$MaxLength" : 10,
			"$Precision" : 8,
			"$Scale" : 2
		}, "2.0");
		testExpression(assert, '<Cast Type="Edm.Decimal" MaxLength="10" Precision="8" Scale="2"'
			+ ' SRID="42"><Float>42</Float></Cast>', {
			"$Cast" : 42,
			"$Type" : "Edm.Decimal",
			"$MaxLength" : 10,
			"$Precision" : 8,
			"$Scale" : 2,
			"$SRID" : "42"
		}, "4.0");
		testExpression(assert, '<Cast Type="Edm.Decimal"/>',
			{"$Cast" : undefined, "$Type" : "Edm.Decimal"});  // do not crash
		testExpression(assert, '<IsOf Type="Collection(f.Type)"><Path>Average</Path></IsOf>', {
			"$IsOf" : {"$Path" : "Average"},
			"$Type" : "foo.Type",
			"$isCollection" : true
		});
		testExpression(assert, '<IsOf Type="Edm.Decimal" MaxLength="10" Precision="8" Scale="2">'
			+ '<Float>42</Float></IsOf>', {
			"$IsOf" : 42,
			"$Type" : "Edm.Decimal",
			"$MaxLength" : 10,
			"$Precision" : 8,
			"$Scale" : 2
		});
		testExpression(assert, '<IsOf Type="Edm.Decimal"/>',
			{"$IsOf" : undefined, "$Type" : "Edm.Decimal"});  // do not crash
	});

	//*********************************************************************************************
	QUnit.test("annotations: Collection", function (assert) {
		testExpression(assert, '<Collection/>', []);
		testExpression(assert,
			'<Collection><String>Product</String><Path>Supplier</Path></Collection>',
			["Product", {"$Path" : "Supplier"}]);
	});

	//*********************************************************************************************
	QUnit.test("annotations: LabeledElement", function (assert) {
		testExpression(assert, '<LabeledElement Name="CustomerFirstName" Path="FirstName" />',
			{"$LabeledElement" : {"$Path" : "FirstName"}, "$Name" : "CustomerFirstName"});
		testExpression(assert,
			'<LabeledElement Name="CustomerFirstName"><Path>FirstName</Path></LabeledElement>',
			{"$LabeledElement" : {"$Path" : "FirstName"}, "$Name" : "CustomerFirstName"});
	});

	//*********************************************************************************************
	QUnit.test("annotations: Record", function (assert) {
		testExpression(assert, '<Record Type="f.Record"/>', {"$Type" : "foo.Record"});
		testExpression(assert, '\
				<Record>\
					<PropertyValue Property="GivenName" Path="FirstName"/>\
					<PropertyValue Property="Surname"><Path>LastName</Path></PropertyValue>\
				</Record>',
			{
				"GivenName" : {"$Path" : "FirstName"},
				"Surname" : {"$Path" : "LastName"}
			});
	});

	//*********************************************************************************************
	QUnit.test("annotations: UrlRef", function (assert) {
		testExpression(assert, '<UrlRef><Path>/Url</Path></UrlRef>',
			{"$UrlRef" : {"$Path" : "/Url"}});
	});
	// TODO look at xml:base if the URL in UrlRef is static and relative

	//*********************************************************************************************
	QUnit.test("annotated expressions", function (assert) {
		testExpression(assert, '\
				<Apply Function="f.Function">\
					<Annotation Term="f.Term" String="Apply"/>\
				</Apply>',
			{
				"$Apply" : [],
				"$Function" : "foo.Function",
				"@foo.Term" : "Apply"
			});
		testExpression(assert, '\
				<Cast Type="Edm.String">\
					<Annotation Term="f.Term" String="Cast"/>\
				</Cast>',
			{
				"$Cast" : undefined,
				"$Type" : "Edm.String",
				"@foo.Term" : "Cast"
			});
		["And", "Eq", "Ge", "Gt", "If", "Le", "Lt", "Ne", "Or"].forEach(
			function (sOperator) {
				var sXml = '<' + sOperator + '><Annotation Term="f.Term" String="Annotation"/></'
						+ sOperator + '>',
					oExpected = {"@foo.Term" : "Annotation"};

				oExpected["$" + sOperator] = [];
				testExpression(assert, sXml, oExpected);
			});
		testExpression(assert, '\
				<IsOf Type="Edm.String">\
					<Annotation Term="f.Term" String="IsOf"/>\
				</IsOf>',
			{
				"$IsOf" : undefined,
				"$Type" : "Edm.String",
				"@foo.Term" : "IsOf"
			});
		testExpression(assert, '\
				<LabeledElement Name="LabeledElement" String="Foo">\
					<Annotation Term="f.Term" String="LabeledElement"/>\
				</LabeledElement>',
			{
				"$Name" : "LabeledElement",
				"$LabeledElement" : "Foo",
				"@foo.Term" : "LabeledElement"
			});
		testExpression(assert, '\
				<Not Type="Edm.String">\
					<Annotation Term="f.Term" String="Not"/>\
				</Not>',
			{
				"$Not" : undefined,
				"@foo.Term" : "Not"
			});
		testExpression(assert, '\
				<Null>\
					<Annotation Term="f.Term" String="Null"/>\
				</Null>',
			{
				"$Null" : null,
				"@foo.Term" : "Null"
			});
		testExpression(assert, '\
				<Record Type="f.Record">\
					<Annotation Term="f.Term" String="Record"/>\
					<PropertyValue Property="GivenName" Path="FirstName">\
						<Annotation Term="f.Term" String="PropertyValue"/>\
					</PropertyValue>\
				</Record>',
			{
				"$Type" : "foo.Record",
				"GivenName" : {"$Path" : "FirstName"},
				"@foo.Term" : "Record",
				"GivenName@foo.Term" : "PropertyValue"
			});
	});
});


text:
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * TipoDocumentoExpediente
 *
 * @ORM\Table(name="tipos_documento_expediente")
 * @ORM\Entity
 */
class TipoDocumentoExpediente
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="descripcion", type="string", length=255)
     */
    private $descripcion;

     /**
     * @ORM\OneToMany(targetEntity="Documento", mappedBy="tipoDocumentoExpediente")
     */
    private $documentos;
    /**
     * @var datetime $creado
     *
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(name="creado", type="datetime")
     */
    private $creado;

    /**
     * @var datetime $actualizado
     *
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(name="actualizado",type="datetime")
     */
    private $actualizado;

    /**
     * @var integer $creadoPor
     *
     * @Gedmo\Blameable(on="create")
     * @ORM\ManyToOne(targetEntity="UsuariosBundle\Entity\Usuario")
     * @ORM\JoinColumn(name="creado_por", referencedColumnName="id", nullable=true)
     */
    private $creadoPor;

    /**
     * @var integer $actualizadoPor
     *
     * @Gedmo\Blameable(on="update")
     * @ORM\ManyToOne(targetEntity="UsuariosBundle\Entity\Usuario")
     * @ORM\JoinColumn(name="actualizado_por", referencedColumnName="id", nullable=true)
     */
    private $actualizadoPor;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set descripcion
     *
     * @param string $descripcion
     *
     * @return TipoDocumentoExpediente
     */
    public function setDescripcion($descripcion)
    {
        $this->descripcion = $descripcion;

        return $this;
    }

    /**
     * Get descripcion
     *
     * @return string
     */
    public function getDescripcion()
    {
        return $this->descripcion;
    }

    /**
     * Set creado
     *
     * @param \DateTime $creado
     *
     * @return TipoDocumentoExpediente
     */
    public function setCreado($creado)
    {
        $this->creado = $creado;

        return $this;
    }

    /**
     * Get creado
     *
     * @return \DateTime
     */
    public function getCreado()
    {
        return $this->creado;
    }

    /**
     * Set actualizado
     *
     * @param \DateTime $actualizado
     *
     * @return TipoDocumentoExpediente
     */
    public function setActualizado($actualizado)
    {
        $this->actualizado = $actualizado;

        return $this;
    }

    /**
     * Get actualizado
     *
     * @return \DateTime
     */
    public function getActualizado()
    {
        return $this->actualizado;
    }

    /**
     * Set creadoPor
     *
     * @param \UsuariosBundle\Entity\Usuario $creadoPor
     *
     * @return TipoDocumentoExpediente
     */
    public function setCreadoPor(\UsuariosBundle\Entity\Usuario $creadoPor = null)
    {
        $this->creadoPor = $creadoPor;

        return $this;
    }

    /**
     * Get creadoPor
     *
     * @return \UsuariosBundle\Entity\Usuario
     */
    public function getCreadoPor()
    {
        return $this->creadoPor;
    }

    /**
     * Set actualizadoPor
     *
     * @param \UsuariosBundle\Entity\Usuario $actualizadoPor
     *
     * @return TipoDocumentoExpediente
     */
    public function setActualizadoPor(\UsuariosBundle\Entity\Usuario $actualizadoPor = null)
    {
        $this->actualizadoPor = $actualizadoPor;

        return $this;
    }

    /**
     * Get actualizadoPor
     *
     * @return \UsuariosBundle\Entity\Usuario
     */
    public function getActualizadoPor()
    {
        return $this->actualizadoPor;
    }

    public function __toString() {
        return $this->descripcion;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->documentos = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add documento
     *
     * @param \AppBundle\Entity\Documento $documento
     *
     * @return TipoDocumentoExpediente
     */
    public function addDocumento(\AppBundle\Entity\Documento $documento)
    {
        $this->documentos[] = $documento;

        return $this;
    }

    /**
     * Remove documento
     *
     * @param \AppBundle\Entity\Documento $documento
     */
    public function removeDocumento(\AppBundle\Entity\Documento $documento)
    {
        $this->documentos->removeElement($documento);
    }

    /**
     * Get documentos
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getDocumentos()
    {
        return $this->documentos;
    }
}

redpajama_set_name: RedPajamaGithub


text: Adding a search query box


text:
/**
 * A Sprite is an object rendered in a Drawing surface.
 *
 * ## Types
 *
 * The following sprite types are supported:
 *
 * ### Rect
 *
 * Rectangle requires `width` and `height` attributes:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: 'rect',
 *             width: 100,
 *             height: 50,
 *             radius: 10,
 *             fill: 'green',
 *             opacity: 0.5,
 *             stroke: 'red',
 *             'stroke-width': 2
 *         }]
 *     });
 *
 * ### Circle
 *
 * Circle requires `x`, `y` and `radius` attributes:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: 'circle',
 *             radius: 90,
 *             x: 100,
 *             y: 100,
 *             fill: 'blue'
 *         }]
 *     });
 *
 * ### Ellipse
 *
 * Ellipse requires `x`, `y`, `radiusX` and `radiusY` attributes:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: "ellipse",
 *             radiusX: 100,
 *             radiusY: 50,
 *             x: 100,
 *             y: 100,
 *             fill: 'red'
 *         }]
 *     });
 *
 * ### Path
 *
 * Path requires the `path` attribute:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: "path",
 *             path: "M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 " +
 *                   "-85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 " +
 *                   "10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 " +
 *                   "24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 " +
 *                   "33.6L-66.6 26z",
 *             fill: "purple"
 *         }]
 *     });
 *
 * ### Text
 *
 * Text requires the `text` attribute:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: "text",
 *             text: "Hello, Sprite!",
 *             fill: "green",
 *             font: "18px monospace"
 *         }]
 *     });
 *
 * ### Image
 *
 * Image requires `width`, `height` and `src` attributes:
 *
 *     @example
 *     Ext.create('Ext.draw.Component', {
 *         renderTo: Ext.getBody(),
 *         width: 200,
 *         height: 200,
 *         items: [{
 *             type: "image",
 *             src: "http://www.sencha.com/img/apple-touch-icon.png",
 *             width: 200,
 *             height: 200
 *         }]
 *     });
 *
 * ## Creating and adding a Sprite to a Surface
 *
 * See {@link Ext.draw.Surface} documentation.
 *
 * ## Transforming sprites
 *
 * See {@link #setAttributes} method documentation for examples on how to translate, scale and rotate the sprites.
 *
 */
Ext.define('Ext.draw.Sprite', {

    /* Begin Definitions */

    mixins: {
        observable: 'Ext.util.Observable',
        animate: 'Ext.util.Animate'
    },

    requires: ['Ext.draw.SpriteDD'],

    /* End Definitions */

    /**
     * @cfg {String} type The type of the sprite.
     * Possible options are 'circle', 'ellipse', 'path', 'rect', 'text', 'image'.
     *
     * See {@link Ext.draw.Sprite} class documentation for examples of all types.
     */

    /**
     * @cfg {Number} width The width of the rect or image sprite.
     */

    /**
     * @cfg {Number} height The height of the rect or image sprite.
     */

    /**
     * @cfg {Number} radius The radius of the circle sprite. Or in case of rect sprite, the border radius.
     */

    /**
     * @cfg {Number} radiusX The radius of the ellipse sprite along x-axis.
     */

    /**
     * @cfg {Number} radiusY The radius of the ellipse sprite along y-axis.
     */

    /**
     * @cfg {Number} x Sprite position along the x-axis.
     */

    /**
     * @cfg {Number} y Sprite position along the y-axis.
     */

    /**
     * @cfg {String} path The path of the path sprite written in SVG-like path syntax.
     */

    /**
     * @cfg {Number} opacity The opacity of the sprite. A number between 0 and 1.
     */

    /**
     * @cfg {String} fill The fill color.
     */

    /**
     * @cfg {String} stroke The stroke color.
     */

    /**
     * @cfg {Number} stroke-width The width of the stroke.
     *
     * Note that this attribute needs to be quoted when used.  Like so:
     *
     *     "stroke-width": 12,
     */

    /**
     * @cfg {String} font Used with text type sprites. The full font description.
     * Uses the same syntax as the CSS font parameter
     */

    /**
     * @cfg {String} text The actual text to render in text sprites.
     */

    /**
     * @cfg {String} src Path to the image to show in image sprites.
     */

    /**
     * @cfg {String/String[]} group The group that this sprite belongs to, or an array of groups.
     * Only relevant when added to a {@link Ext.draw.Surface Surface}.
     */

    /**
     * @cfg {Boolean} draggable True to make the sprite draggable.
     */

    dirty: false,
    dirtyHidden: false,
    dirtyTransform: false,
    dirtyPath: true,
    dirtyFont: true,
    zIndexDirty: true,

    /**
     * @property {Boolean} isSprite
     * `true` in this class to identify an object as an instantiated Sprite, or subclass thereof.
     */
    isSprite: true,
    zIndex: 0,
    fontProperties: [
        'font',
        'font-size',
        'font-weight',
        'font-style',
        'font-family',
        'text-anchor',
        'text'
    ],
    pathProperties: [
        'x',
        'y',
        'd',
        'path',
        'height',
        'width',
        'radius',
        'r',
        'rx',
        'ry',
        'cx',
        'cy'
    ],
    constructor: function(config) {
        var me = this;
        config = Ext.merge({}, config || {});
        me.id = Ext.id(null, 'ext-sprite-');
        me.transformations = [];
        Ext.copyTo(this, config, 'surface,group,type,draggable');
        //attribute bucket
        me.bbox = {};
        me.attr = {
            zIndex: 0,
            translation: {
                x: null,
                y: null
            },
            rotation: {
                degrees: null,
                x: null,
                y: null
            },
            scaling: {
                x: null,
                y: null,
                cx: null,
                cy: null
            }
        };
        //delete not bucket attributes
        delete config.surface;
        delete config.group;
        delete config.type;
        delete config.draggable;
        me.setAttributes(config);
        me.addEvents(
            /**
             * @event
             * Fires before the sprite is destroyed. Return false from an event handler to stop the destroy.
             * @param {Ext.draw.Sprite} this
             */
            'beforedestroy',
            /**
             * @event
             * Fires after the sprite is destroyed.
             * @param {Ext.draw.Sprite} this
             */
            'destroy',
            /**
             * @event
             * Fires after the sprite markup is rendered.
             * @param {Ext.draw.Sprite} this
             */
            'render',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#mousedown
             */
            'mousedown',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#mouseup
             */
            'mouseup',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#mouseover
             */
            'mouseover',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#mouseout
             */
            'mouseout',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#mousemove
             */
            'mousemove',
            /**
             * @event
             * @inheritdoc Ext.dom.Element#click
             */
            'click'
        );
        me.mixins.observable.constructor.apply(this, arguments);
    },

    /**
     * @property {Ext.dd.DragSource} dd
     * If this Sprite is configured {@link #draggable}, this property will contain
     * an instance of {@link Ext.dd.DragSource} which handles dragging the Sprite.
     *
     * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
     * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
     */

    initDraggable: function() {
        var me = this;
        //create element if it doesn't exist.
        if (!me.el) {
            me.surface.createSpriteElement(me);
        }
        me.dd = new Ext.draw.SpriteDD(me, Ext.isBoolean(me.draggable) ? null : me.draggable);
        me.on('beforedestroy', me.dd.destroy, me.dd);
    },

    /**
     * Change the attributes of the sprite.
     *
     * ## Translation
     *
     * For translate, the configuration object contains x and y attributes that indicate where to
     * translate the object. For example:
     *
     *     sprite.setAttributes({
     *       translate: {
     *        x: 10,
     *        y: 10
     *       }
     *     }, true);
     *
     *
     * ## Rotation
     *
     * For rotation, the configuration object contains x and y attributes for the center of the rotation (which are optional),
     * and a `degrees` attribute that specifies the rotation in degrees. For example:
     *
     *     sprite.setAttributes({
     *       rotate: {
     *        degrees: 90
     *       }
     *     }, true);
     *
     * That example will create a 90 degrees rotation using the centroid of the Sprite as center of rotation, whereas:
     *
     *     sprite.setAttributes({
     *       rotate: {
     *        x: 0,
     *        y: 0,
     *        degrees: 90
     *       }
     *     }, true);
     *
     * will create a rotation around the `(0, 0)` axis.
     *
     *
     * ## Scaling
     *
     * For scaling, the configuration object contains x and y attributes for the x-axis and y-axis scaling. For example:
     *
     *     sprite.setAttributes({
     *       scale: {
     *        x: 10,
     *        y: 3
     *       }
     *     }, true);
     *
     * You can also specify the center of scaling by adding `cx` and `cy` as properties:
     *
     *     sprite.setAttributes({
     *       scale: {
     *        cx: 0,
     *        cy: 0,
     *        x: 10,
     *        y: 3
     *       }
     *     }, true);
     *
     * That last example will scale a sprite taking as centers of scaling the `(0, 0)` coordinate.
     *
     * @param {Object} attrs attributes to be changed on the sprite.
     * @param {Boolean} redraw Flag to immediately draw the change.
     * @return {Ext.draw.Sprite} this
     */
    setAttributes: function(attrs, redraw) {
        var me = this,
            fontProps = me.fontProperties,
            fontPropsLength = fontProps.length,
            pathProps = me.pathProperties,
            pathPropsLength = pathProps.length,
            hasSurface = !!me.surface,
            custom = hasSurface && me.surface.customAttributes || {},
            spriteAttrs = me.attr,
            dirtyBBox = false,
            attr, i, newTranslation, translation, newRotate, rotation, newScaling, scaling;

        attrs = Ext.apply({}, attrs);
        for (attr in custom) {
            if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
                Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
            }
        }

        // Flag a change in hidden
        if (!!attrs.hidden !== !!spriteAttrs.hidden) {
            me.dirtyHidden = true;
        }

        // Flag path change
        for (i = 0; i < pathPropsLength; i++) {
            attr = pathProps[i];
            if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
                me.dirtyPath = true;
                dirtyBBox = true;
                break;
            }
        }

        // Flag zIndex change
        if ('zIndex' in attrs) {
            me.zIndexDirty = true;
        }

        // Flag font/text change
        if ('text' in attrs) {
            me.dirtyFont = true;
            dirtyBBox = true;
        }

        for (i = 0; i < fontPropsLength; i++) {
            attr = fontProps[i];
            if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
                me.dirtyFont = true;
                dirtyBBox = true;
                break;
            }
        }

        newTranslation = attrs.translation || attrs.translate;
        delete attrs.translate;
        delete attrs.translation;
        translation = spriteAttrs.translation;
        if (newTranslation) {
            if (('x' in newTranslation && newTranslation.x !== translation.x) ||
                ('y' in newTranslation && newTranslation.y !== translation.y)) {
                me.dirtyTransform = true;
                translation.x = newTranslation.x;
                translation.y = newTranslation.y;
            }
        }

        newRotate = attrs.rotation || attrs.rotate;
        rotation = spriteAttrs.rotation;
        delete attrs.rotate;
        delete attrs.rotation;
        if (newRotate) {
            if (('x' in newRotate && newRotate.x !== rotation.x) ||
                ('y' in newRotate && newRotate.y !== rotation.y) ||
                ('degrees' in newRotate && newRotate.degrees !== rotation.degrees)) {
                me.dirtyTransform = true;
                rotation.x = newRotate.x;
                rotation.y = newRotate.y;
                rotation.degrees = newRotate.degrees;
            }
        }

        newScaling = attrs.scaling || attrs.scale;
        scaling = spriteAttrs.scaling;
        delete attrs.scale;
        delete attrs.scaling;
        if (newScaling) {
            if (('x' in newScaling && newScaling.x !== scaling.x) ||
                ('y' in newScaling && newScaling.y !== scaling.y) ||
                ('cx' in newScaling && newScaling.cx !== scaling.cx) ||
                ('cy' in newScaling && newScaling.cy !== scaling.cy)) {
                me.dirtyTransform = true;
                scaling.x = newScaling.x;
                scaling.y = newScaling.y;
                scaling.cx = newScaling.cx;
                scaling.cy = newScaling.cy;
            }
        }

        // If the bbox is changed, then the bbox based transforms should be invalidated.
        if (!me.dirtyTransform && dirtyBBox) {
            if (spriteAttrs.scaling.x === null ||
                spriteAttrs.scaling.y === null ||
                spriteAttrs.rotation.y === null ||
                spriteAttrs.rotation.y === null) {
                me.dirtyTransform = true;
            }
        }

        Ext.apply(spriteAttrs, attrs);
        me.dirty = true;

        if (redraw === true && hasSurface) {
            me.redraw();
        }
        return this;
    },

    /**
     * Retrieves the bounding box of the sprite.
     * This will be returned as an object with x, y, width, and height properties.
     * @return {Object} bbox
     */
    getBBox: function() {
        return this.surface.getBBox(this);
    },

    setText: function(text) {
        return this.surface.setText(this, text);
    },

    /**
     * Hides the sprite.
     * @param {Boolean} redraw Flag to immediately draw the change.
     * @return {Ext.draw.Sprite} this
     */
    hide: function(redraw) {
        this.setAttributes({
            hidden: true
        }, redraw);
        return this;
    },

    /**
     * Shows the sprite.
     * @param {Boolean} redraw Flag to immediately draw the change.
     * @return {Ext.draw.Sprite} this
     */
    show: function(redraw) {
        this.setAttributes({
            hidden: false
        }, redraw);
        return this;
    },

    /**
     * Removes the sprite.
     * @return {Boolean} True if sprite was successfully removed.
     * False when there was no surface to remove it from.
     */
    remove: function() {
        if (this.surface) {
            this.surface.remove(this);
            return true;
        }
        return false;
    },

    onRemove: function() {
        this.surface.onRemove(this);
    },

    /**
     * Removes the sprite and clears all listeners.
     */
    destroy: function() {
        var me = this;
        if (me.fireEvent('beforedestroy', me) !== false) {
            me.remove();
            me.surface.onDestroy(me);
            me.clearListeners();
            me.fireEvent('destroy');
        }
    },

    /**
     * Redraws the sprite.
     * @return {Ext.draw.Sprite} this
     */
    redraw: function() {
        this.surface.renderItem(this);
        return this;
    },

    /**
     * Wrapper for setting style properties, also takes single object parameter of multiple styles.
     * @param {String/Object} property The style property to be set, or an object of multiple styles.
     * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
     * @return {Ext.draw.Sprite} this
     */
    setStyle: function() {
        this.el.setStyle.apply(this.el, arguments);
        return this;
    },

    /**
     * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.  Note this method
     * is severly limited in VML.
     * @param {String/String[]} className The CSS class to add, or an array of classes
     * @return {Ext.draw.Sprite} this
     */
    addCls: function(obj) {
        this.surface.addCls(this, obj);
        return this;
    },

    /**
     * Removes one or more CSS classes from the element.
     * @param {String/String[]} className The CSS class to remove, or an array of classes.  Note this method
     * is severly limited in VML.
     * @return {Ext.draw.Sprite} this
     */
    removeCls: function(obj) {
        this.surface.removeCls(this, obj);
        return this;
    }
});


text:
(function () {
  'use strict';

  angular
    .module('core.common.config')
    .provider('fuseConfig', fuseConfigProvider);

  /** @ngInject */
  function fuseConfigProvider() {
    // Default configuration
    var fuseConfiguration = {
      'disableCustomScrollbars': false,
      'disableMdInkRippleOnMobile': true,
      'disableCustomScrollbarsOnMobile': true
    };

    // Methods
    this.config = config;

    // // // // //

    /**
     * Extend default configuration with the given one
     *
     * @param configuration
     */
    function config(configuration) {
      fuseConfiguration = angular.extend({}, fuseConfiguration, configuration);
    }

    /**
     * Service
     */
    this.$get = function () {
      var service = {
        getConfig: getConfig,
        setConfig: setConfig
      };

      return service;

      // // // // //

      /**
       * Returns a config value
       */
      function getConfig(configName) {
        if (angular.isUndefined(fuseConfiguration[configName])) {
          return false;
        }

        return fuseConfiguration[configName];
      }

      /**
       * Creates or updates config object
       *
       * @param configName
       * @param configValue
       */
      function setConfig(configName, configValue) {
        fuseConfiguration[configName] = configValue;
      }
    };
  }

}());


text:
mod foo {
    pub mod bar {}
}

use foo::bar;
extern crate issue_45829_b as bar;
//~^ ERROR the name `bar` is defined multiple times

fn main() {}


text:
import _Ajv from "../ajv"
import chai from "../chai"
chai.should()

describe("issue #485, order of type validation", () => {
  it("should validate types before keywords", () => {
    const ajv = new _Ajv({allErrors: true, strictTypes: false})
    const validate: any = ajv.compile({
      type: ["integer", "string"],
      required: ["foo"],
      minimum: 2,
    })

    validate(2).should.equal(true)
    validate("foo").should.equal(true)

    validate(1.5).should.equal(false)
    checkErrors(["type", "minimum"])

    validate({}).should.equal(false)
    checkErrors(["type", "required"])

    function checkErrors(expectedErrs) {
      validate.errors.should.have.length(expectedErrs.length)
      expectedErrs.forEach((keyword, i) => validate.errors[i].keyword.should.equal(keyword))
    }
  })
})


text:
chorus.views.Dashboard = chorus.views.Base.extend({
    constructorName: "DashboardView",
    templateName:"dashboard/main",
    subviews: {
        '.dashboard_main': "dashboardMain",
        '.data_source_list': "dataSourceList",
        '.workspace_list': "workspaceList",
        '.project_list': "projectList"
    },

    setup: function() {
        this.memberWorkspaces = new chorus.collections.WorkspaceSet();
        this.memberWorkspaces.attributes = _.extend({}, this.collection.attributes);
        this.memberWorkspaces.attributes.userId = chorus.session.user().id;

        this.projectWorkspaces = new chorus.collections.WorkspaceSet();
        this.projectWorkspaces.attributes = _.extend({}, this.collection.attributes);

        this.workspaceList = new chorus.views.MainContentView({
            collection: this.memberWorkspaces,
            contentHeader: new chorus.views.StaticTemplate("default_content_header", {title:t("header.my_workspaces")}),
            contentDetails:new chorus.views.StaticTemplate("dashboard/workspace_list_content_details"),
            content:new chorus.views.DashboardWorkspaceList({ collection: this.memberWorkspaces })
        });

        this.projectList = new chorus.views.MainContentView({
            collection: this.projectWorkspaces,
            contentHeader: new chorus.views.ProjectListHeader({collection: this.projectWorkspaces}),
            content: new chorus.views.DashboardProjectList({ collection: this.projectWorkspaces })
        });

        this.dataSourceList = new chorus.views.MainContentView({
            collection: this.options.dataSourceSet,
            contentHeader: new chorus.views.StaticTemplate("default_content_header", {title:t("header.browse_data")}),
            contentDetails: new chorus.views.StaticTemplate("dashboard/data_source_list_content_details"),
            content: new chorus.views.DashboardDataSourceList({ collection: this.options.dataSourceSet })
        });

        var activities = new chorus.collections.ActivitySet([]);
        activities.attributes.pageSize = 50;

        activities.fetch();
        this.activityList = new chorus.views.ActivityList({ collection: activities, additionalClass: "dashboard" });
        this.dashboardMain = new chorus.views.MainContentView({
            content: this.activityList,
            contentHeader: new chorus.views.ActivityListHeader({
                collection: activities,
                allTitle: t("dashboard.title.activity"),
                insightsTitle: t("dashboard.title.insights")
            })
        });

        if (this.collection.loaded) {
            this.collectionUpdated();
        }
        this.listenTo(this.collection, 'loaded', this.collectionUpdated);
    },

    collectionUpdated: function () {
        this.memberWorkspaces.loaded = true;
        this.projectWorkspaces.loaded = true;
        this.memberWorkspaces.reset(this.collection.where({isMember: true}));
        this.memberWorkspaces.trigger('loaded');
        this.projectWorkspaces.reset(this.collection.where({isProject: true}));
        this.projectWorkspaces.trigger('loaded');
    }
});


text:
package cn.tomoya.config.freemarker;

import cn.tomoya.module.reply.entity.Reply;
import cn.tomoya.module.reply.service.ReplyService;
import cn.tomoya.module.topic.entity.Topic;
import cn.tomoya.module.user.entity.User;
import cn.tomoya.module.user.service.UserService;
import freemarker.core.Environment;
import freemarker.template.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * xgb on 17-6-12.
 */
@Component
public class RepliesDirective implements TemplateDirectiveModel {

  @Autowired
  private ReplyService replyService;
  @Autowired
  private UserService userService;

  @Override
  public void execute(Environment environment, Map map, TemplateModel[] templateModels,
                      TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
    DefaultObjectWrapperBuilder builder = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);

    int topicId = Integer.parseInt(map.get("id").toString());
    Topic topic = new Topic();
    topic.setId(topicId);

    List<Reply> replies = replyService.findByTopic(topic);
    environment.setVariable("replies", builder.build().wrap(replies));

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication.isAuthenticated() && authentication.getPrincipal() instanceof UserDetails) {
      User user = userService.findByUsername(((UserDetails) authentication.getPrincipal()).getUsername());
      environment.setVariable("user", builder.build().wrap(user));
    }

    templateDirectiveBody.render(environment.getOut());
  }
}


text:
YUI.add('node-focusmanager', function(Y) {

/**
*
The Focus Manager Node Plugin makes it easy to manage focus among
* a Node's descendants.  Primarily intended to help with widget development,
* the Focus Manager Node Plugin can be used to improve the keyboard
* accessibility of widgets.

*
*

* When designing widgets that manage a set of descendant controls (i.e. buttons
* in a toolbar, tabs in a tablist, menuitems in a menu, etc.) it is important to
* limit the number of descendants in the browser's default tab flow.  The fewer
* number of descendants in the default tab flow, the easier it is for keyboard
* users to navigate between widgets by pressing the tab key.  When a widget has
* focus it should provide a set of shortcut keys (typically the arrow keys)
* to move focus among its descendants.
*

*
*

* To this end, the Focus Manager Node Plugin makes it easy to define a Node's
* focusable descendants, define which descendant should be in the default tab
* flow, and define the keys that move focus among each descendant.
* Additionally, as the CSS
* :focus
* pseudo class is not supported on all elements in all
* A-Grade browsers,
* the Focus Manager Node Plugin provides an easy, cross-browser means of
* styling focus.
*

*
* @module node-focusmanager
*/

	//	Frequently used strings

var ACTIVE_DESCENDANT = "activeDescendant",
	ID = "id",
	DISABLED = "disabled",
	TAB_INDEX = "tabIndex",
	FOCUSED = "focused",
	FOCUS_CLASS = "focusClass",
	CIRCULAR = "circular",
	UI = "UI",
	KEY = "key",
	ACTIVE_DESCENDANT_CHANGE = ACTIVE_DESCENDANT + "Change",
	HOST = "host",

	//	Collection of keys that, when pressed, cause the browser viewport
	//	to scroll.
	scrollKeys = {
		37: true,
		38: true,
		39: true,
		40: true
	},

	clickableElements = {
		"a": true,
		"button": true,
		"input": true,
		"object": true
	},

	//	Library shortcuts

	Lang = Y.Lang,
 	UA = Y.UA,

	/**
	* The NodeFocusManager class is a plugin for a Node instance.  The class is used
	* via the plug method of Node
	* and should not be instantiated directly.
	* @namespace plugin
	* @class NodeFocusManager
	*/
	NodeFocusManager = function () {

		NodeFocusManager.superclass.constructor.apply(this, arguments);

	};

NodeFocusManager.ATTRS = {

	/**
	* Boolean indicating that one of the descendants is focused.
	*
	* @attribute focused
	* @readOnly
	* @default false
	* @type boolean
	*/
	focused: {

		value: false,
		readOnly: true

	},

	/**
	* String representing the CSS selector used to define the descendant Nodes
	* whose focus should be managed.
	*
	* @attribute descendants
	* @type Y.NodeList
	*/
	descendants: {

		getter: function (value) {

			return this.get(HOST).all(value);

		}

	},

	/**
	*
Node, or index of the Node, representing the descendant that is either
	* focused or is focusable (tabIndex attribute is set to 0).
	* The value cannot represent a disabled descendant Node.  Use a value of -1
	* to remove all descendant Nodes from the default tab flow.
	* If no value is specified, the active descendant will be inferred using
	* the following criteria:

	*

	*
Examining the tabIndex attribute of each descendant and
	* using the first descendant whose tabIndex attribute is set
	* to 0

	*
If no default can be inferred then the value is set to either 0 or
	* the index of the first enabled descendant.

	*

	*
	* @attribute activeDescendant
	* @type Number
	*/
	activeDescendant: {

		setter: function (value) {

			var isNumber = Lang.isNumber,
				INVALID_VALUE = Y.Attribute.INVALID_VALUE,
				descendantsMap = this._descendantsMap,
				descendants = this._descendants,
				nodeIndex,
				returnValue,
				oNode;

			if (isNumber(value)) {
				nodeIndex = value;
				returnValue = nodeIndex;
			}
			else if ((value instanceof Y.Node) && descendantsMap) {

				nodeIndex = descendantsMap[value.get(ID)];

				if (isNumber(nodeIndex)) {
					returnValue = nodeIndex;
				}
				else {

					//	The user passed a reference to a Node that wasn't one
					//	of the descendants.
					returnValue = INVALID_VALUE;

				}

			}
			else {
				returnValue = INVALID_VALUE;
			}

			if (descendants) {

				oNode = descendants.item(nodeIndex);

				if (oNode && oNode.get("disabled")) {

					//	Setting the "activeDescendant" attribute to the index
					//	of a disabled descendant is invalid.
					returnValue = INVALID_VALUE;

				}

			}

			return returnValue;

		}

	},

	/**
	* Object literal representing the keys to be used to navigate between the
	* next/previous descendant.  The format for the attribute's value is
	* { next: "down:40", previous: "down:38" }.  The value for the
	* "next" and "previous" properties are used to attach
	* key event listeners. See
	* the Using the key Event section of
	* the Event documentation for more information on "key" event listeners.
	*
	* @attribute keys
	* @type Object
	*/
	keys: {

		value: {

			next: null,
			previous: null

		}

	},

	/**
	* String representing the name of class applied to the focused active
	* descendant Node.  Can also be an object literal used to define both the
	* class name, and the Node to which the class should be applied.  If using
	* an object literal, the format is:
	* { className: "focus", fn: myFunction }.  The function
	* referenced by the fn property in the object literal will be
	* passed a reference to the currently focused active descendant Node.
	*
	* @attribute focusClass
	* @type String|Object
	*/
	focusClass: { },

	/**
	* Boolean indicating if focus should be set to the first/last descendant
	* when the end or beginning of the descendants has been reached.
	*
	* @attribute circular
	* @type Boolean
	*/
	circular: {
		value: true
	}

};

Y.extend(NodeFocusManager, Y.Plugin.Base, {

	//	Protected properties

	//	Boolean indicating if the NodeFocusManager is active.
	_stopped: true,

	//	NodeList representing the descendants selected via the
	//	"descendants" attribute.
	_descendants: null,

	//	Object literal mapping the IDs of each descendant to its index in the
	//	"_descendants" NodeList.
	_descendantsMap: null,

	//	Reference to the Node instance to which the focused class (defined
	//	by the "focusClass" attribute) is currently applied.
	_focusedNode: null,

	//	Number representing the index of the last descendant Node.
	_lastNodeIndex: 0,

	//	Array of handles for event handlers used for a NodeFocusManager instance.
	_eventHandlers: null,

	//	Protected methods

	/**
	* @method _initDescendants
	* @description Sets the tabIndex attribute of all of the
	* descendants to -1, except the active descendant, whose
	* tabIndex attribute is set to 0.
	* @protected
	*/
	_initDescendants: function () {

		var descendants = this.get("descendants"),
			descendantsMap = {},
			nFirstEnabled = -1,
			nDescendants,
			nActiveDescendant = this.get(ACTIVE_DESCENDANT),
			oNode,
			sID,
			i = 0;

		if (Lang.isUndefined(nActiveDescendant)) {
			nActiveDescendant = -1;
		}

		if (descendants) {

			nDescendants = descendants.size();

            for (i = 0; i < nDescendants; i++) {

                oNode = descendants.item(i);

                if (nFirstEnabled === -1 && !oNode.get(DISABLED)) {
                    nFirstEnabled = i;
                }

                //	If the user didn't specify a value for the
                //	"activeDescendant" attribute try to infer it from
                //	the markup.

                //	Need to pass "2" when using "getAttribute" for IE to get
                //	the attribute value as it is set in the markup.
                //	Need to use "parseInt" because IE always returns the
                //	value as a number, whereas all other browsers return
                //	the attribute as a string when accessed
                //	via "getAttribute".

                if (nActiveDescendant < 0 &&
                        parseInt(oNode.getAttribute(TAB_INDEX, 2), 10) === 0) {

                    nActiveDescendant = i;

                }

                if (oNode) {
                    oNode.set(TAB_INDEX, -1);
                }

                sID = oNode.get(ID);

                if (!sID) {
                    sID = Y.guid();
                    oNode.set(ID, sID);
                }

                descendantsMap[sID] = i;

            }

            //	If the user didn't specify a value for the
            //	"activeDescendant" attribute and no default value could be
            //	determined from the markup, then default to 0.

            if (nActiveDescendant < 0) {
                nActiveDescendant = 0;
            }

            oNode = descendants.item(nActiveDescendant);

            //	Check to make sure the active descendant isn't disabled,
            //	and fall back to the first enabled descendant if it is.

            if (!oNode || oNode.get(DISABLED)) {
                oNode = descendants.item(nFirstEnabled);
                nActiveDescendant = nFirstEnabled;
            }

            this._lastNodeIndex = nDescendants - 1;
            this._descendants = descendants;
            this._descendantsMap = descendantsMap;

            this.set(ACTIVE_DESCENDANT, nActiveDescendant);

            //	Need to set the "tabIndex" attribute here, since the
            //	"activeDescendantChange" event handler used to manage
            //	the setting of the "tabIndex" attribute isn't wired up yet.

            if (oNode) {
                oNode.set(TAB_INDEX, 0);
            }

		}

	},

	/**
	* @method _isDescendant
	* @description Determines if the specified Node instance is a descendant
	* managed by the Focus Manager.
	* @param node {Node} Node instance to be checked.
	* @return {Boolean} Boolean indicating if the specified Node instance is a
	* descendant managed by the Focus Manager.
	* @protected
	*/
	_isDescendant: function (node) {

		return (node.get(ID) in this._descendantsMap);

	},

	/**
	* @method _removeFocusClass
	* @description Removes the class name representing focus (as specified by
	* the "focusClass" attribute) from the Node instance to which it is
	* currently applied.
	* @protected
	*/
	_removeFocusClass: function () {

		var oFocusedNode = this._focusedNode,
			focusClass = this.get(FOCUS_CLASS),
			sClassName;

		if (focusClass) {
			sClassName = Lang.isString(focusClass) ?
				focusClass : focusClass.className;
		}

		if (oFocusedNode && sClassName) {
			oFocusedNode.removeClass(sClassName);
		}

	},

	/**
	* @method _detachKeyHandler
	* @description Detaches the "key" event handlers used to support the "keys"
	* attribute.
	* @protected
	*/
	_detachKeyHandler: function () {

		var prevKeyHandler = this._prevKeyHandler,
			nextKeyHandler = this._nextKeyHandler;

		if (prevKeyHandler) {
			prevKeyHandler.detach();
		}

		if (nextKeyHandler) {
			nextKeyHandler.detach();
		}

	},

	/**
	* @method _preventScroll
	* @description Prevents the viewport from scolling when the user presses
	* the up, down, left, or right key.
	* @protected
	*/
	_preventScroll: function (event) {

		if (scrollKeys[event.keyCode] && this._isDescendant(event.target)) {
			event.preventDefault();
		}

	},

	/**
	* @method _fireClick
	* @description Fires the click event if the enter key is pressed while
	* focused on an HTML element that is not natively clickable.
	* @protected
	*/
	_fireClick: function (event) {

		var oTarget = event.target,
			sNodeName = oTarget.get("nodeName").toLowerCase();

		if (event.keyCode === 13 && (!clickableElements[sNodeName] ||
				(sNodeName === "a" && !oTarget.getAttribute("href")))) {

			oTarget.simulate("click");

		}

	},

	/**
	* @method _attachKeyHandler
	* @description Attaches the "key" event handlers used to support the "keys"
	* attribute.
	* @protected
	*/
	_attachKeyHandler: function () {

		this._detachKeyHandler();

		var sNextKey = this.get("keys.next"),
			sPrevKey = this.get("keys.previous"),
			oNode = this.get(HOST),
			aHandlers = this._eventHandlers;

		if (sPrevKey) {
 			this._prevKeyHandler =
				Y.on(KEY, Y.bind(this._focusPrevious, this), oNode, sPrevKey);
		}

		if (sNextKey) {
 			this._nextKeyHandler =
				Y.on(KEY, Y.bind(this._focusNext, this), oNode, sNextKey);
		}

		//	In Opera it is necessary to call the "preventDefault" method in
		//	response to the user pressing the arrow keys in order to prevent
		//	the viewport from scrolling when the user is moving focus among
		//	the focusable descendants.

		if (UA.opera) {
			aHandlers.push(oNode.on("keypress", this._preventScroll, this));
		}

		//	For all browsers except Opera: HTML elements that are not natively
		//	focusable but made focusable via the tabIndex attribute don't
		//	fire a click event when the user presses the enter key.  It is
		//	possible to work around this problem by simplying dispatching a
		//	click event in response to the user pressing the enter key.

		if (!UA.opera) {
			aHandlers.push(oNode.on("keypress", this._fireClick, this));
		}

	},

	/**
	* @method _detachEventHandlers
	* @description Detaches all event handlers used by the Focus Manager.
	* @protected
	*/
	_detachEventHandlers: function () {

		this._detachKeyHandler();

		var aHandlers = this._eventHandlers;

		if (aHandlers) {

			Y.Array.each(aHandlers, function (handle) {
				handle.detach();
			});

			this._eventHandlers = null;

		}

	},

	/**
	* @method _detachEventHandlers
	* @description Attaches all event handlers used by the Focus Manager.
	* @protected
	*/
	_attachEventHandlers: function () {

		var descendants = this._descendants,
			aHandlers,
			oDocument,
			handle;

		if (descendants && descendants.size()) {

			aHandlers = this._eventHandlers || [];
			oDocument = this.get(HOST).get("ownerDocument");

			if (aHandlers.length === 0) {

				aHandlers.push(oDocument.on("focus", this._onDocFocus, this));

				aHandlers.push(oDocument.on("mousedown",
					this._onDocMouseDown, this));

				aHandlers.push(
						this.after("keysChange", this._attachKeyHandler));

				aHandlers.push(
						this.after("descendantsChange", this._initDescendants));

				aHandlers.push(
						this.after(ACTIVE_DESCENDANT_CHANGE,
								this._afterActiveDescendantChange));

				//	For performance: defer attaching all key-related event
				//	handlers until the first time one of the specified
				//	descendants receives focus.

				handle = this.after("focusedChange", Y.bind(function (event) {

					if (event.newVal) {

						this._attachKeyHandler();

						//	Detach this "focusedChange" handler so that the
						//	key-related handlers only get attached once.

						handle.detach();

					}

				}, this));

				aHandlers.push(handle);

			}

			this._eventHandlers = aHandlers;

		}

	},

	//	Protected event handlers

	/**
	* @method _onDocMouseDown
	* @description "mousedown" event handler for the owner document of the
	* Focus Manager's Node.
	* @protected
	* @param event {Object} Object representing the DOM event.
	*/
	_onDocMouseDown: function (event) {

		var oHost = this.get(HOST),
			oTarget = event.target,
			bChildNode = oHost.contains(oTarget),
			node,

			getFocusable = function (node) {

				var returnVal = false;

				if (!node.compareTo(oHost)) {

					returnVal = this._isDescendant(node) ? node :
									getFocusable.call(this, node.get("parentNode"));

				}

				return returnVal;

			};

		if (bChildNode) {

			//	Check to make sure that the target isn't a child node of one
			//	of the focusable descendants.

			node = getFocusable.call(this, oTarget);

			if (node) {
				oTarget = node;
			}
			else if (!node && this.get(FOCUSED)) {

				//	The target was a non-focusable descendant of the root
				//	node, so the "focused" attribute should be set to false.

	 			this._set(FOCUSED, false);
	 			this._onDocFocus(event);

			}

		}

		if (bChildNode && this._isDescendant(oTarget)) {

			//	Fix general problem in Webkit: mousing down on a button or an
			//	anchor element doesn't focus it.

			//	For all browsers: makes sure that the descendant that
			//	was the target of the mousedown event is now considered the
			//	active descendant.

			this.focus(oTarget);
		}
		else if (UA.webkit && this.get(FOCUSED) &&
			(!bChildNode || (bChildNode && !this._isDescendant(oTarget)))) {

			//	Fix for Webkit:

			//	Document doesn't receive focus in Webkit when the user mouses
			//	down on it, so the "focused" attribute won't get set to the
			//	correct value.

			//	The goal is to force a blur if the user moused down on
			//	either: 1) A descendant node, but not one that managed by
			//	the FocusManager, or 2) an element outside of the
			//	FocusManager

 			this._set(FOCUSED, false);
 			this._onDocFocus(event);

		}

	},

	/**
	* @method _onDocFocus
	* @description "focus" event handler for the owner document of the
	* Focus Manager's Node.
	* @protected
	* @param event {Object} Object representing the DOM event.
	*/
	_onDocFocus: function (event) {

		var oTarget = this._focusTarget || event.target,
			bFocused = this.get(FOCUSED),
			focusClass = this.get(FOCUS_CLASS),
			oFocusedNode = this._focusedNode,
			bInCollection;

		if (this._focusTarget) {
			this._focusTarget = null;
		}

		if (this.get(HOST).contains(oTarget)) {

			//	The target is a descendant of the root Node.

			bInCollection = this._isDescendant(oTarget);

			if (!bFocused && bInCollection) {

				//	The user has focused a focusable descendant.

				bFocused = true;

			}
			else if (bFocused && !bInCollection) {

				//	The user has focused a child of the root Node that is
				//	not one of the descendants managed by this Focus Manager
				//	so clear the currently focused descendant.

				bFocused = false;

			}

		}
		else {

			// The target is some other node in the document.

			bFocused = false;

		}

		if (focusClass) {

			if (oFocusedNode && (!oFocusedNode.compareTo(oTarget) || !bFocused)) {
				this._removeFocusClass();
			}

			if (bInCollection && bFocused) {

				if (focusClass.fn) {
					oTarget = focusClass.fn(oTarget);
					oTarget.addClass(focusClass.className);
				}
				else {
					oTarget.addClass(focusClass);
				}

				this._focusedNode = oTarget;

			}

		}

		this._set(FOCUSED, bFocused);

	},

	/**
	* @method _focusNext
	* @description Keydown event handler that moves focus to the next
	* enabled descendant.
	* @protected
	* @param event {Object} Object representing the DOM event.
	* @param activeDescendant {Number} Number representing the index of the
	* next descendant to be focused
	*/
	_focusNext: function (event, activeDescendant) {

		var nActiveDescendant = activeDescendant || this.get(ACTIVE_DESCENDANT),
			oNode;

		if (this._isDescendant(event.target) &&
			(nActiveDescendant <= this._lastNodeIndex)) {

			nActiveDescendant = nActiveDescendant + 1;

			if (nActiveDescendant === (this._lastNodeIndex + 1) &&
				this.get(CIRCULAR)) {

				nActiveDescendant = 0;

			}

			oNode = this._descendants.item(nActiveDescendant);

            if (oNode) {

                if (oNode.get("disabled")) {
                    this._focusNext(event, nActiveDescendant);
                }
                else {
                    this.focus(nActiveDescendant);
                }

            }

		}

		this._preventScroll(event);

	},

	/**
	* @method _focusPrevious
	* @description Keydown event handler that moves focus to the previous
	* enabled descendant.
	* @protected
	* @param event {Object} Object representing the DOM event.
	* @param activeDescendant {Number} Number representing the index of the
	* next descendant to be focused.
	*/
	_focusPrevious: function (event, activeDescendant) {

		var nActiveDescendant = activeDescendant || this.get(ACTIVE_DESCENDANT),
			oNode;

		if (this._isDescendant(event.target) && nActiveDescendant >= 0) {

			nActiveDescendant = nActiveDescendant - 1;

			if (nActiveDescendant === -1 && this.get(CIRCULAR)) {
				nActiveDescendant = this._lastNodeIndex;
			}

            oNode = this._descendants.item(nActiveDescendant);

            if (oNode) {

                if (oNode.get("disabled")) {
                    this._focusPrevious(event, nActiveDescendant);
                }
                else {
                    this.focus(nActiveDescendant);
                }

            }

		}

		this._preventScroll(event);

	},

	/**
	* @method _afterActiveDescendantChange
	* @description afterChange event handler for the
	* "activeDescendant" attribute.
	* @protected
	* @param event {Object} Object representing the change event.
	*/
	_afterActiveDescendantChange: function (event) {

		var oNode = this._descendants.item(event.prevVal);

		if (oNode) {
			oNode.set(TAB_INDEX, -1);
		}

		oNode = this._descendants.item(event.newVal);

		if (oNode) {
			oNode.set(TAB_INDEX, 0);
		}

	},

	//	Public methods

    initializer: function (config) {

		this.start();

    },

	destructor: function () {

		this.stop();
		this.get(HOST).focusManager = null;

    },

	/**
	* @method focus
	* @description Focuses the active descendant and sets the
	* focused attribute to true.
	* @param index {Number} Optional. Number representing the index of the
	* descendant to be set as the active descendant.
	* @param index {Node} Optional. Node instance representing the
	* descendant to be set as the active descendant.
	*/
	focus: function (index) {

		if (Lang.isUndefined(index)) {
			index = this.get(ACTIVE_DESCENDANT);
		}

		this.set(ACTIVE_DESCENDANT, index, { src: UI });

		var oNode = this._descendants.item(this.get(ACTIVE_DESCENDANT));

		if (oNode) {

			oNode.focus();

			//	In Opera focusing a <BUTTON> element programmatically
			//	will result in the document-level focus event handler
			//	"_onDocFocus" being called, resulting in the handler
			//	incorrectly setting the "focused" Attribute to false.  To fix
			//	this, set a flag ("_focusTarget") that the "_onDocFocus" method
			//	can look for to properly handle this edge case.

			if (UA.opera && oNode.get("nodeName").toLowerCase() === "button") {
				this._focusTarget = oNode;
			}

		}

	},

	/**
	* @method blur
	* @description Blurs the current active descendant and sets the
	* focused attribute to false.
	*/
	blur: function () {

		var oNode;

		if (this.get(FOCUSED)) {

			oNode = this._descendants.item(this.get(ACTIVE_DESCENDANT));

			if (oNode) {

				oNode.blur();

				//	For Opera and Webkit:  Blurring an element in either browser
				//	doesn't result in another element (such as the document)
				//	being focused.  Therefore, the "_onDocFocus" method
				//	responsible for managing the application and removal of the
				//	focus indicator class name is never called.

				this._removeFocusClass();

			}

			this._set(FOCUSED, false, { src: UI });
		}

	},

	/**
	* @method start
	* @description Enables the Focus Manager.
	*/
	start: function () {

		if (this._stopped) {

			this._initDescendants();
			this._attachEventHandlers();

			this._stopped = false;

		}

	},

	/**
	* @method stop
	* @description Disables the Focus Manager by detaching all event handlers.
	*/
	stop: function () {

		if (!this._stopped) {

			this._detachEventHandlers();

			this._descendants = null;
			this._focusedNode = null;
			this._lastNodeIndex = 0;
			this._stopped = true;

		}

	},

	/**
	* @method refresh
	* @description Refreshes the Focus Manager's descendants by re-executing the
	* CSS selector query specified by the descendants attribute.
	*/
	refresh: function () {

		this._initDescendants();

		if (!this._eventHandlers) {
			this._attachEventHandlers();
		}

	}

});

NodeFocusManager.NAME = "nodeFocusManager";
NodeFocusManager.NS = "focusManager";

Y.namespace("Plugin");
Y.Plugin.NodeFocusManager = NodeFocusManager;

}, '3.3.0' ,{requires:['attribute', 'node', 'plugin', 'node-event-simulate', 'event-key', 'event-focus']});


text:
package com.brucezee.jspider.redis;

import com.brucezee.jspider.Request;
import com.brucezee.jspider.Task;
import com.brucezee.jspider.scheduler.handler.RepeatHandler;
import com.brucezee.jspider.paging.PagingRequestFactory;
import com.brucezee.jspider.serializer.Serializer;
import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Set;

/**
 * 实现redis优先执行的请求任务调度器
 * Created by brucezee on 2017/1/16.
 */
public class RedisPriorityScheduler extends RedisScheduler {
    public RedisPriorityScheduler(JedisPool jedisPool) {
        super(jedisPool);
    }

    public RedisPriorityScheduler(JedisPool jedisPool, Serializer<Request> serializer) {
        super(jedisPool, serializer);
    }

    public RedisPriorityScheduler(JedisPool jedisPool, Serializer<Request> serializer, RepeatHandler repeatHandler, PagingRequestFactory pagingRequestFactory) {
        super(jedisPool, serializer, repeatHandler, pagingRequestFactory);
    }

    @Override
    protected void pushWhenNoRepeat(Task task, Request request) {
        Jedis jedis = jedisPool.getResource();
        try {
            String content = serializer.serialize(request);
            if(request.getPriority() == 0) {
                jedis.rpush(RedisKeys.getQueueNoPriorityKey(task), content);
            } else if (request.getPriority() > 0) {
                jedis.zadd(RedisKeys.getZsetPlusPriorityKey(task), request.getPriority(), content);
            } else {
                jedis.zadd(RedisKeys.getZsetMinusPriorityKey(task), request.getPriority(), content);
            }

            jedis.sadd(RedisKeys.getSetKey(task), request.key());
        } finally {
            jedis.close();
        }
    }

    @Override
    public Request doPoll(Task task) {
        Jedis jedis = jedisPool.getResource();
        try {
            String content = null;
            Set<String> contents = jedis.zrevrange(RedisKeys.getZsetPlusPriorityKey(task), 0, 0);
            if (contents != null && !contents.isEmpty()) {
                content = contents.toArray(new String[0])[0];
                jedis.zrem(RedisKeys.getZsetPlusPriorityKey(task), content);
            } else {
                content = jedis.lpop(RedisKeys.getQueueNoPriorityKey(task));
                if (StringUtils.isBlank(content)) {
                    contents = jedis.zrevrange(RedisKeys.getZsetMinusPriorityKey(task), 0, 0);
                    if (contents != null && !contents.isEmpty()) {
                        content = contents.toArray(new String[0])[0];
                        jedis.zrem(RedisKeys.getZsetPlusPriorityKey(task), content);
                    }
                }
            }

            return StringUtils.isNotBlank(content) ? serializer.deserialize(content) : null;
        } finally {
            jedis.close();
        }
    }
}


text:
#include "SIM_EulerGAS.h"

// Public
EulerGAS2D::EulerGAS2D(){
  user_params.clear();
  u.clear(); u0.clear();
  v.clear(); v0.clear();
  uw.clear(); vw.clear();
  d.clear(); d0.clear();
  t.clear(); t0.clear();
  omega.clear(); omega0.clear();
  inside_mask.clear(); inside_mask0.clear();
  nodal_solid_phi.clear();
  pressure_solver_params.clear();
  particles_container.clear();
  source_locations.clear();
  external_force_locations.clear();
  domain_boundaries[0].side = EDGES_2DSIM::TOP;
	domain_boundaries[0].boundaryType = BOUNDARY::STREAK;
	domain_boundaries[1].side = EDGES_2DSIM::BOTTOM;
	domain_boundaries[1].boundaryType = BOUNDARY::STREAK;
	domain_boundaries[2].side = EDGES_2DSIM::RIGHT;
	domain_boundaries[2].boundaryType = BOUNDARY::STREAK;
	domain_boundaries[3].side = EDGES_2DSIM::LEFT;
	domain_boundaries[3].boundaryType = BOUNDARY::STREAK;
}

// Public
EulerGAS2D::EulerGAS2D(const EulerGAS2D& src){
  u = src.u; u0 = src.u0;
  v = src.v; v0 = src.v0;
  uw = src.uw; vw = src.vw;
  d = src.v; d0 = src.v0;
  t = src.v; t0 = src.v0;
  omega = src.v; omega0 = src.v0;
  user_params = src.user_params;
  inside_mask = src.inside_mask; inside_mask0 = src.inside_mask0;
  nodal_solid_phi = src.nodal_solid_phi;
  particles_container = src.particles_container;
  source_locations = src.source_locations;
  external_force_locations = src.external_force_locations;
}

// Public
EulerGAS2D::EulerGAS2D(Parameters _user_params):user_params(_user_params){
  v.Reset(_user_params.dimension.m_x, _user_params.dimension.m_y + 1, _user_params.h, _user_params.h); v0 = v;
  u.Reset(_user_params.dimension.m_x + 1, _user_params.dimension.m_y, _user_params.h, _user_params.h); u0 = u;
  uw.Reset(_user_params.dimension.m_x + 1, _user_params.dimension.m_y, _user_params.h, _user_params.h);
  vw.Reset(_user_params.dimension.m_x, _user_params.dimension.m_y + 1, _user_params.h, _user_params.h);
  d.Reset(_user_params.dimension.m_x, _user_params.dimension.m_y, _user_params.h, _user_params.h); d0 = d;
  t.Reset(_user_params.dimension.m_x, _user_params.dimension.m_y, _user_params.h, _user_params.h); t0 = t;
  omega.Reset(_user_params.dimension.m_x + 2, _user_params.dimension.m_y + 2, _user_params.h, _user_params.h); omega0 = omega;
  nodal_solid_phi.Reset(_user_params.dimension.m_x + 1, _user_params.dimension.m_y + 1, _user_params.h, _user_params.h);
  inside_mask.Reset(_user_params.dimension.m_x + 1, _user_params.dimension.m_y + 1, _user_params.h, _user_params.h); inside_mask0 = inside_mask;
  particles_container.resize(_user_params.num_particles);
  source_locations.resize(0);
  external_force_locations.resize(0);
}

// Public
EulerGAS2D&
EulerGAS2D::operator=(const EulerGAS2D& rhs){
  u = rhs.u; u0 = rhs.u0;
  v = rhs.v; v0 = rhs.v0;
  uw = rhs.uw; vw = rhs.vw;
  d = rhs.v; d0 = rhs.v0;
  t = rhs.v; t0 = rhs.v0;
  omega = rhs.v; omega0 = rhs.v0;
  inside_mask = rhs.inside_mask; inside_mask0 = rhs.inside_mask0;
  user_params = rhs.user_params;
  particles_container = rhs.particles_container;
  source_locations = rhs.source_locations;
  external_force_locations = rhs.external_force_locations;
  return *this;
}

// Public
EulerGAS2D::~EulerGAS2D(){
  close();
}

// Public
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
bool
EulerGAS2D::init(Parameters params){
  user_params = params;
  v.Reset(user_params.dimension.m_x, user_params.dimension.m_y + 1, user_params.h, user_params.h); v0 = v;
  u.Reset(user_params.dimension.m_x + 1, user_params.dimension.m_y, user_params.h, user_params.h); u0 = u;
  uw.Reset(user_params.dimension.m_x + 1, user_params.dimension.m_y, user_params.h, user_params.h);
  vw.Reset(user_params.dimension.m_x, user_params.dimension.m_y + 1, user_params.h, user_params.h);
  d.Reset(user_params.dimension.m_x, user_params.dimension.m_y, user_params.h, user_params.h); d0 = d;
  t.Reset(user_params.dimension.m_x, user_params.dimension.m_y, user_params.h, user_params.h); t0 = t;
  omega.Reset(user_params.dimension.m_x + 2, user_params.dimension.m_y + 2, user_params.h, user_params.h); omega0 = omega;
  nodal_solid_phi.Reset(user_params.dimension.m_x + 1, user_params.dimension.m_y + 1, user_params.h, user_params.h);
  particles_container.resize(user_params.num_particles);

  // Make the mask all as boundaries in initialization
  inside_mask.Reset(user_params.dimension.m_x + 1, user_params.dimension.m_y + 1, user_params.h, user_params.h); inside_mask0 = inside_mask;
  for(int i = 0; i != inside_mask.getDimY(); i++){
    for(int j = 0; j != inside_mask.getDimX(); j++){
      inside_mask(i, j) = VFXEpoch::BOUNDARY_MASK::SOMETHING;
      inside_mask0(i, j) = inside_mask(i, j);
    }
  }

  return true;
}

// Public
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
void
EulerGAS2D::step(){
  if(0 != source_locations.size())  add_source();
  cout << "--> Advect particles" << endl;
  advect_particles();
  cout << "--> Advect velocity (Self-Advection)" << endl;
  advect_vel();
  if(0 != external_force_locations.size()) add_force();
  cout << "--> Solving pressure" << endl;
  project();
  cout << "--> Pressure linear solver (pcg) outputs:" << endl;
  cout << " ->  Tolerance:" << user_params.out_tolerance << endl;
  cout << " ->  iterations:" << user_params.out_iterations << endl;
  cout << "--> Looking for boundaries" << endl;
  find_boundary(u, uw, inside_mask, inside_mask0);
  find_boundary(v, vw, inside_mask, inside_mask0);
  cout << "--> Solving boundary conditions" << endl;
  correct_vel();

}

// Public
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
void
EulerGAS2D::close(){
  u.clear(); u0.clear();
  v.clear(); v0.clear();
  d.clear(); d0.clear();
  t.clear(); t0.clear();
  omega.clear(); omega0.clear();
  inside_mask.clear(); inside_mask0.clear();
  nodal_solid_phi.clear();
  user_params.clear();
  particles_container.clear();
  source_locations.clear();
}

// Public
void
EulerGAS2D::set_source_location(int i, int j){
  assert(i >= 0 && j >= 0 && i < user_params.dimension.m_y && j < user_params.dimension.m_x);
  source_locations.push_back(VFXEpoch::Vector2Di(i, j));
}

// Public
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
void
EulerGAS2D::add_source(){
  for(std::vector<VFXEpoch::Vector2Di>::iterator ite = source_locations.begin(); ite != source_locations.end(); ite++){
    assert(ite->m_x >= 0 && ite->m_x < d.getDimY() && ite->m_y >= 0 && ite->m_y < d.getDimX());
    d(ite->m_x, ite->m_y) = user_params.density_source;
  }
}

// Public
void
EulerGAS2D::set_external_force_location(VFXEpoch::VECTOR_COMPONENTS component, int i, int j){
  if(VFXEpoch::VECTOR_COMPONENTS::X == component){
    assert(i >= 0 && i <= u.getDimY() && j >= 0 && j <= u.getDimX());
    external_force_locations.push_back(VFXEpoch::Vector3Di(i, j, 0));
  }
  else if(VFXEpoch::VECTOR_COMPONENTS::Y == component){
    assert(i >= 0 && i <= v.getDimY() && j >= 0 && j <= v.getDimX());
    external_force_locations.push_back(VFXEpoch::Vector3Di(i, j, 1));
  }
  else{
    std::cout << "Component error occured!" << endl;
  }
}

// Protected
void
EulerGAS2D::add_force(){
  // In this function, we use the the last compoenent of a 3D vector to specify adding the source
  // to u component or v compoenent
  for(std::vector<VFXEpoch::Vector3Di>::iterator ite = external_force_locations.begin(); ite != external_force_locations.end(); ite++){
    if(0 == ite->m_z){
      assert(ite->m_x >= 0 && ite->m_x < u.getDimY() && ite->m_y >= 0 && ite->m_y < u.getDimX());
      u(ite->m_x, ite->m_y) = user_params.external_force_strength;
    } else {
      assert(ite->m_x >= 0 && ite->m_x < v.getDimY() && ite->m_y >= 0 && ite->m_y < v.getDimX());
      v(ite->m_x, ite->m_y) = user_params.external_force_strength;
    }
  }

  if (user_params.use_gravity){
    float grav = -981.0f * user_params.dt;
    LOOP_GRID2D(v){
      v(i, j) += grav;
    }
  }
}

// Public
void
EulerGAS2D::add_particles(VFXEpoch::Particle2Df p){
  particles_container.push_back(p);
}

// Public
void
EulerGAS2D::set_inside_boundary(Grid2DCellTypes boundaries){
  assert(inside_mask.getDimX() == boundaries.getDimX() && inside_mask.getDimY() == boundaries.getDimY());
  inside_mask = boundaries;
}

// Public
void
EulerGAS2D::set_domain_boundary(const VFXEpoch::BOUNDARY boundary_type, const VFXEpoch::EDGES_2DSIM edge){
  if(VFXEpoch::EDGES_2DSIM::TOP == edge){
    domain_boundaries[0].side = edge;
    domain_boundaries[0].boundaryType = boundary_type;
  } else if(VFXEpoch::EDGES_2DSIM::BOTTOM == edge){
    domain_boundaries[1].side = edge;
    domain_boundaries[1].boundaryType = boundary_type;
  } else if(VFXEpoch::EDGES_2DSIM::LEFT == edge){
    domain_boundaries[2].side = edge;
    domain_boundaries[2].boundaryType = boundary_type;
  } else{
    domain_boundaries[3].side = edge;
    domain_boundaries[3].boundaryType = boundary_type;
  }
}

// Public
void
EulerGAS2D::set_static_boundary(float (*phi)(const VFXEpoch::Vector2Df&)){
  LOOP_GRID2D(nodal_solid_phi){
    VFXEpoch::Vector2Df position(i * user_params.h, j * user_params.h);
    nodal_solid_phi(i, j) = phi(position + user_params.origin);
  }
}

// Public
vector<VFXEpoch::Particle2Df>
EulerGAS2D::get_particles(){
  return particles_container;
}

// Public
void
EulerGAS2D::set_user_params(Parameters params){
  user_params = params;
}

EulerGAS2D::Parameters
EulerGAS2D::get_user_params() const {
  return user_params;
}

// Public
VFXEpoch::Vector2Df
EulerGAS2D::get_grid_velocity(VFXEpoch::Vector2Df pos) {
  return get_vel(pos);
}

// Protected
void
EulerGAS2D::set_domain_boundary_wrapper(Grid2DfScalarField& field){
  for(int i = 0; i != 4; i++){
    field.setBoundaries(domain_boundaries[i].boundaryType, domain_boundaries[i].side);
  }
  field.setBoundariesOnCorners();
}

// Protected
// TODO: Check fast linear solvercorrectness for dx, dy, dimension in vertical & horizontal
void
EulerGAS2D::density_diffuse(Grid2DfScalarField& dest, Grid2DfScalarField ref){
  float a = user_params.diff * user_params.dt * user_params.dimension.m_x * user_params.dimension.m_y;
  VFXEpoch::LinearSolver::GSSolve(dest, ref, domain_boundaries, a, 1+4*a, user_params.max_iterations);
}

// Protected
// TODO: Check fast linear solver correctness for dx, dy, dimension in vertical & horizontal
void
EulerGAS2D::dynamic_diffuse(Grid2DfScalarField& dest, Grid2DfScalarField ref){
  float a = user_params.visc * user_params.dt * user_params.dimension.m_x * user_params.dimension.m_y;
  VFXEpoch::LinearSolver::GSSolve(dest, ref, domain_boundaries, a, 1+4*a, user_params.max_iterations);
}

// Protected
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
void
EulerGAS2D::advect_vel(){
  // Using RK2 method time integration
  // advect u component of velocity field
  LOOP_GRID2D(u0){
    VFXEpoch::Vector2Df pos(j * user_params.h, (i+0.5f) * user_params.h);
    pos = trace_rk2(pos, -user_params.dt);
    u0(i, j) = get_vel(pos).m_x;
  }

  // advect v component of velocity field
  LOOP_GRID2D(v0){
    VFXEpoch::Vector2Df pos((j+0.5f) * user_params.h, i * user_params.h);
    pos = trace_rk2(pos, -user_params.dt);
    v0(i, j) = get_vel(pos).m_y;
  }
  u = u0;
  v = v0;
}

// Protected
void
EulerGAS2D::advect_den(){
  // Using RK2 method time integration
  // advect density field
  // Brutal turning over the boundaries
  assert(d0.getDimX() == inside_mask.getDimX() && d0.getDimY() == inside_mask.getDimY());
  LOOP_GRID2D(d0){
      VFXEpoch::Vector2Df pos((j+0.5f) * user_params.h, (i+0.5f) * user_params.h);
      pos = trace_rk2(pos, -user_params.dt);
      d0(i, j) = get_den(pos);
  }
  d = d0;
}

// Protected
void
EulerGAS2D::advect_tmp(){
  assert(t0.getDimX() == inside_mask.getDimX() && t0.getDimY() == inside_mask.getDimY());
  LOOP_GRID2D(t0){
      VFXEpoch::Vector2Df pos((j+0.5f) * user_params.h, (i+0.5f) * user_params.h);
      pos = trace_rk2(pos, -user_params.dt);
      t0(i, j) = get_tmp(pos);
  }
  t = t0;
}

// Protected
void
EulerGAS2D::advect_curl(){
  // Using RK2 method time integration
  // advect curl field
  assert(omega0.getDimX() == omega.getDimX() && omega0.getDimY() == omega0.getDimY());
  LOOP_GRID2D(omega0){
    VFXEpoch::Vector2Df pos((j+0.5f) * user_params.h, (i+0.5f) * user_params.h);
    pos = trace_rk2(pos, -user_params.dt);
    omega0(i, j) = get_curl(pos);
  }
  omega = omega0;
}

// Protected
void
EulerGAS2D::advect_particles(){
  std::vector<VFXEpoch::Particle2Df>::iterator ite(0);
  for(ite = particles_container.begin(); ite != particles_container.end(); ite++){
    ite->pos = trace_rk2(ite->pos, user_params.dt);

    // Correction particles at the boundaries
    float h = user_params.h;
    float corrections = VFXEpoch::InterpolateGrid(ite->pos / h, nodal_solid_phi);
    if(corrections < 0.0f){
      VFXEpoch::Vector2Df normal;
      VFXEpoch::InterpolateGradient(normal, ite->pos / h, nodal_solid_phi);
      normal.normalize();
      ite->pos -= corrections * normal;
    }
  }
}

// Protected
void
EulerGAS2D::project(){
  pressure_solve();
  apply_gradients();
}

// Protected
void
EulerGAS2D::apply_buoyancy(){
  // Dimension check
  assert(v0.getDimX() == v.getDimX() && v0.getDimY() == v.getDimY());

  float a = user_params.buoyancy_alpha;
  float b = user_params.buoyancy_beta;
  int row = user_params.dimension.m_y;
  int col = user_params.dimension.m_x;
  LOOP_GRID2D(v0){
    if(0 == i || j == 0) continue;
    float average_temperature = (t(i, j) + t(i, j - 1)) * 0.5f;
    float average_density = (d(i, j) + d(i, j - 1)) * 0.5f;
    v0(i, j) = v(i, j) - a * average_density + b * average_temperature;
  }
  v = v0;
}

//Protected
Vector2Df
EulerGAS2D::trace_rk2(const Vector2Df& pos, float dt){
  Vector2Df vel = get_vel(pos);
  vel = get_vel(pos + 0.5f * dt * vel);
  return Vector2Df(pos + dt * vel);
}

// Protected
// Overload from SIM_Base.h -> class Euler_Fluid2D_Base
void
EulerGAS2D::pressure_solve(){
  // System size check and resize;
  int system_size = user_params.dimension.m_x * user_params.dimension.m_y;
  if(pressure_solver_params.pressure.size() != system_size){
    pressure_solver_params.rhs.resize(system_size);
    pressure_solver_params.pressure.resize(system_size);
    pressure_solver_params.sparse_matrix.resize(system_size);
  }

  VFXEpoch::Grid2DdScalarField div(user_params.dimension.m_x, user_params.dimension.m_y, user_params.h, user_params.h);
  get_grid_weights();
  VFXEpoch::Analysis::computeDivergence_with_weights_mac(div, user_params.h, u, v, uw, vw);
  pressure_solver_params.rhs = div.toVector();
  setup_pressure_coef_matrix();

  // TODO: Invoke pcgsolver interface to setup the solver inside parameters
  pressure_solver_params.pcg_solver.set_solver_parameters(user_params.min_tolerance, user_params.max_iterations);
  bool success = pressure_solver_params.pcg_solver.solve(pressure_solver_params.sparse_matrix,
                                                         pressure_solver_params.rhs,
                                                         pressure_solver_params.pressure,
                                                         user_params.out_tolerance,
                                                         user_params.out_iterations);
  if(!success){
    #ifdef __linux__
    std:: cout << "\033[1;33mWARNING: Pressure solve failed!\033[0m" << endl;
    #elif __WIN32__
    std::cout <<  "WARNING: Pressure solve failed!" << endl;
    #endif
  }
}

// Protected
// Issues here, when no value set for nodal_solid_phi. Program crashes
// as accessing out of range of pressure
void
EulerGAS2D::apply_gradients(){
  VFXEpoch::Grid2DdScalarField _pressure(user_params.dimension.m_x, user_params.dimension.m_y);
  std::vector<double> solvedPressure(pressure_solver_params.pressure.begin(), pressure_solver_params.pressure.end());
  VFXEpoch::DataFromVectorToGrid(solvedPressure, _pressure);
  float dt = user_params.dt;
  float dx = user_params.h;
  LOOP_GRID2D(u){
    if(uw(i, j) > 0){
      u(i, j) -= dt * (_pressure(i, j) - _pressure(i, j - 1)) / dx;
    } else {
      u(i, j) = 0.0f;
    }
  }

  LOOP_GRID2D(v){
    if(vw(i, j) > 0){
      v(i, j) -= dt * (_pressure(i, j) - _pressure(i - 1, j)) / dx;
    } else {
      v(i, j) = 0.0f;
    }
  }
}

// Protected
void
EulerGAS2D::find_boundary(Grid2DfScalarField& grid,
                        const Grid2DfScalarField& weights,
                        Grid2DCellTypes& mask,
                        Grid2DCellTypes& mask0){
  LOOP_GRID2D(grid){
    mask(i, j) = weights(i, j) > 0.0f ? BOUNDARY_MASK::NOTHING : BOUNDARY_MASK::SOMETHING;
  }

  for(int i = 0; i != 5; i++){
    mask0 = mask;
    LOOP_GRID2D_WITHOUT_DOMAIN_BOUNDARY(grid){
      float sum = 0.0f;
      int count = 0;

      if(BOUNDARY_MASK::SOMETHING == mask0(i, j)){
        if(BOUNDARY_MASK::NOTHING == mask0(i, j+1)){
          sum += grid(i, j+1);
          ++count;
        }

        if(BOUNDARY_MASK::NOTHING == mask0(i, j-1)){
          sum += grid(i, j-1);
          ++count;
        }

        if(BOUNDARY_MASK::NOTHING == mask0(i+1, j)){
          sum += grid(i+1, j);
          ++count;
        }

        if(BOUNDARY_MASK::NOTHING == mask0(i-1, j)){
          sum += grid(i-1, j);
          ++count;
        }

        else {
          /* TODO: ... */
        }

        if(count > 0){
          grid(i, j) = sum / (float)count;
          mask(i, j) = BOUNDARY_MASK::NOTHING;
        }
      }
    }
  }
}

// Protected
void
EulerGAS2D::get_grid_weights(){
  LOOP_GRID2D(uw){
    // TODO: Access out of range "nodal_solid_phi"
    uw(i, j) = 1 - VFXEpoch::InteralFrac(nodal_solid_phi(i+1, j), nodal_solid_phi(i, j));
  }

  LOOP_GRID2D(vw){
    vw(i, j) = 1 - VFXEpoch::InteralFrac(nodal_solid_phi(i, j+1), nodal_solid_phi(i, j));
  }
}

// Protected
void
EulerGAS2D::correct_vel(){
  u0 = u; v0 = v;
  float h = user_params.h;
  LOOP_GRID2D(u){
    if(uw(i, j) == 0.0f){
      VFXEpoch::Vector2Df pos(j * h, (i+0.5) * h);
      VFXEpoch::Vector2Df vel = get_vel(pos);
      VFXEpoch::Vector2Df normal(0.0f, 0.0f);
      VFXEpoch::InterpolateGradient(normal, pos / h, nodal_solid_phi);
      normal.normalize();
      float correction_component = VFXEpoch::Vector2Df::dot(vel, normal);
      vel -= correction_component * normal;
      u0(i, j) = vel.m_x;
    }
  }

  LOOP_GRID2D(v){
    if(vw(i, j) == 0.0f){
      VFXEpoch::Vector2Df pos((j+0.5f) * h, i * h);
      VFXEpoch::Vector2Df vel = get_vel(pos);
      VFXEpoch::Vector2Df normal(0.0f, 0.0f);
      VFXEpoch::InterpolateGradient(normal, pos / h, nodal_solid_phi);
      normal.normalize();
      float correction_component = VFXEpoch::Vector2Df::dot(vel, normal);
      vel -= correction_component * normal;
      v0(i, j) = vel.m_y;
    }
  }
  u = u0; v = v0;
}

// Protected
void
EulerGAS2D::setup_pressure_coef_matrix(){
  int row = user_params.dimension.m_y;
  int col = user_params.dimension.m_x;
  int idx = 0;
  double val = 0.0;
  float dx = user_params.h;
  float dt = user_params.dt;
  int grid_each_row_elements = user_params.dimension.m_x;
  pressure_solver_params.sparse_matrix.zero();
  LOOP_GRID2D_WITHOUT_DOMAIN_BOUNDARY(row, col){
    idx = i * user_params.dimension.m_x + j;
    val = uw(i, j+1) * dt / std::pow(dx, 2.0f);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx,val);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx + 1, -val);
    val = uw(i, j) * dt / std::pow(dx, 2.0f);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx, val);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx - 1, -val);
    val = vw(i+1, j) * dt / std::pow(dx, 2.0f);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx, val);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx + grid_each_row_elements, -val);
    val = vw(i, j) * dt / std::pow(dx, 2.0f);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx, val);
    pressure_solver_params.sparse_matrix.add_to_element(idx, idx - grid_each_row_elements, -val);
  }
}

// Protected
Vector2Df
EulerGAS2D::get_vel(const Vector2Df& pos){
  assert(user_params.h != 0);
  float _u = VFXEpoch::InterpolateGrid(pos / (float)user_params.h - Vector2Df(0.0f, 0.5f), u);
  float _v = VFXEpoch::InterpolateGrid(pos / (float)user_params.h - Vector2Df(0.5f, 0.0f), v);
  return Vector2Df(_u, _v);
}

// Protected
float
EulerGAS2D::get_den(const Vector2Df& pos){
  assert(user_params.h != 0);
  float h = user_params.h;
  return VFXEpoch::InterpolateGrid(pos / h - Vector2Df(0.5f, 0.5f), d);
}

// Protected
float
EulerGAS2D::get_curl(const Vector2Df& pos){
  assert(user_params.h != 0);
  float h = user_params.h;
  return VFXEpoch::InterpolateGrid(pos / h - Vector2Df(0.5f, 0.5f), omega);
}

// Protected
float
EulerGAS2D::get_tmp(const Vector2Df& pos){
  assert(user_params.h != 0);
  float h = user_params.h;
  return VFXEpoch::InterpolateGrid(pos / h - Vector2Df(0.5f, 0.5f), t);
}