X Factor's Vinnie Jones thanks Simon Cowell for helping him through grief
Vinnie Jones has thanked Simon Cowell for helping him with his grief on X Factor: Celebrity following the death of his wife Tanya earlier this year.
The 54-year-old actor, who was voted out of the competition ahead of next week’s hotly-anticipated final alongside Try Star, lost his partner Tanya after a long battle with cancer back in July,
Having previously admitted that he’d signed up to the show because his partner was a massive fan, Vinnie heaped praise on Simon after his exit in a heartwarming video message shared on his socials.
Advertisement Advertisement
‘Been a fantastic journey, absolutely enjoyed it,’ Vinnie began. ‘Simon, thank you so much for getting me through my grief, helping me a hell of a lot with it.
‘I will always be indebted to you my friend. Thank you very much.’
He added: ‘All the fans out there, I’ve had a terrific time.’
In 2013, Vinnie revealed both he and Tanya had melanoma, the most serious type of skin cancer, and he was later given the all-clear.
Tanya had also been treated twice for cervical cancer and underwent a heart transplant at 21 following the birth of her daughter Kaley.
They discovered last Christmas Eve that her cancer had spread to her brain, but she pushed through the festive period while in pain for the benefit of friends and family. She tragically passed away at the family home in Los Angeles surrounded by loved ones in July.
Vinnie paid tribute to Tanya throughout his journey on X Factor: Celebrity by singing her favourite songs.
He also revealed to Metro.co.uk that he believed Tanya would be ‘singing every word’ with him throughout his performance last night, telling us: ‘She’ll be with me on that stage, I’m sure of it.’
Advertisement Advertisement
Sadly Vinnie received the least votes from the public and left the competition yesterday, with just Jenny Ryan, Max and Harvey, V5 and Megan McKenna making it to next week’s final.
The X Factor: Celebrity final airs Saturday at 7.10pm on ITV.
Got a showbiz story?
If you've got a story, video or pictures get in touch with the Metro.co.uk Entertainment team by emailing us<EMAIL_ADDRESS>calling 020 3615 2145 or by visiting our Submit Stuff page - we'd love to hear from you.


Computes the gradients of convolution with respect to the input.
tf.compat.v1.nn.conv2d_backprop_input( input_sizes, filter=None, out_backprop=None, strides=None, padding=None, use_cudnn_on_gpu=True, data_format='NHWC', dilations=[1, 1, 1, 1], name=None, filters=None )
input_sizes
: A Tensor
of type int32
.
An integer vector representing the shape of input
,
where input
is a 4-D [batch, height, width, channels]
tensor.filter
: A Tensor
. Must be one of the following types:
half
, bfloat16
, float32
, float64
.
4-D with shape
[filter_height, filter_width, in_channels, out_channels]
.out_backprop
: A Tensor
. Must have the same type as filter
.
4-D with shape [batch, out_height, out_width, out_channels]
.
Gradients w.r.t. the output of the convolution.strides
: A list of ints
.
The stride of the sliding window for each dimension of the input
of the convolution. Must be in the same order as the dimension specified
with format.padding
: Either the string
"SAME"or
"VALID"indicating the type of
padding algorithm to use, or a list indicating the explicit paddings at
the start and end of each dimension. When explicit padding is used and
data_format is
"NHWC", this should be in the form
[[0, 0], [pad_top,
pad_bottom], [pad_left, pad_right], [0, 0]]. When explicit padding used
and data_format is
"NCHW", this should be in the form
[[0, 0], [0, 0],
[pad_top, pad_bottom], [pad_left, pad_right]]`.use_cudnn_on_gpu
: An optional bool
. Defaults to True
.data_format
: An optional string
from: "NHWC", "NCHW"
.
Defaults to "NHWC"
.
Specify the data format of the input and output data. With the
default format "NHWC", the data is stored in the order of:
[batch, in_height, in_width, in_channels].
Alternatively, the format could be "NCHW", the data storage order of:
[batch, in_channels, in_height, in_width].dilations
: An optional list of ints
. Defaults to [1, 1, 1, 1]
.
1-D tensor of length 4. The dilation factor for each dimension of
input
. If set to k > 1, there will be k-1 skipped cells between each
filter element on that dimension. The dimension order is determined by
the value of data_format
, see above for details. Dilations in the batch
and depth dimensions must be 1.name
: A name for the operation (optional).filters
: Alias for filter.A Tensor
. Has the same type as filter
.


Mining
Virtual Bitcoin includes mining functions. The mining site is as follows.
https://mining.vbitco.in
Virtual Bitcoin includes mining functions. The mining site is as follows.
https://mining.vbitco.in


public interface ReferenceSetAugmentor
ExternalReferenceTranslatorSPI
and
ExternalReferenceBuilderSPI
to build external references from,
respectively, other external references and from streams. These are then used
to augment the contents of implementations of ReferenceSet
with
additional ExternalReferenceSPI
implementations.
Methods in this interface throw the runtime exception
ReferenceSetAugmentationException
for all problems, other exceptions
are wrapped in this type and re-thrown.
| Modifier and Type | Method and Description |
|---|---|
Set<ExternalReferenceSPI> |
augmentReferenceSet(ReferenceSet references,
Set<Class<ExternalReferenceSPI>> targetReferenceTypes,
ReferenceContext context)
Attempts to modify the supplied ReferenceSet such that it contains an
implementation of at least one of the ExternalReferenceSPI classes
specified.
|
void |
augmentReferenceSetAsynch(ReferenceSet references,
Set<Class<ExternalReferenceSPI>> targetReferenceTypes,
ReferenceContext context,
ReferenceSetAugmentorCallback callback)
As with
augmentReferenceSet(ReferenceSet, Set, ReferenceContext)
but called in an asynchronous fashion. |
Set<ExternalReferenceSPI> augmentReferenceSet(ReferenceSet references, Set<Class<ExternalReferenceSPI>> targetReferenceTypes, ReferenceContext context) throws ReferenceSetAugmentationException
references
- reference set object to augmenttargetReferenceTypes
- a set of Class objects, this method succeeds if it can create
an instance of at least one of these pointing to the same data
as the other external references in the supplied reference setcontext
- a reference resolution context, potentially required for
access to the existing references or for creation of the
augmentationsReferenceSetAugmentationException
- if a problem occurs either in configuration of the
ReferenceSetAugmentor or in the augmentation process itself.
Any other exception types are wrapped in this and re-thrown.void augmentReferenceSetAsynch(ReferenceSet references, Set<Class<ExternalReferenceSPI>> targetReferenceTypes, ReferenceContext context, ReferenceSetAugmentorCallback callback) throws ReferenceSetAugmentationException
augmentReferenceSet(ReferenceSet, Set, ReferenceContext)
but called in an asynchronous fashion. Returns immediately and uses the
supplied instance of ReferenceSetAugmentorCallback
to provide
either the augmented ReferenceSet
or an exception indicating a
failure in the augmentation process.callback
- callback object used to indicate failure or to return the
modified reference setReferenceSetAugmentationException
- if the ReferenceSetAugmentor is missing critical
configuration. Exceptions that happen during augmentation or
as a result of a failure to find an appropriate augmentation
path are signalled by calls to the callback object, this
method only throws the exception if it can't even try to do
the augmentation for some reason.Copyright © 2015–2016 The Apache Software Foundation. All rights reserved.


by doy (jluehrs2 at uiuc dot edu)
updated by THC4k (http://www.ls-themes.org)
LSLua is a scripting interface to LiteStep using the Lua scripting language. Lua is a cross platform, open source, embeddable scripting language. This module provides an interface to the LSAPI through Lua scripts.
This document explains what LSLua as a module provides;
for convenience, each of lua code
,
litestep config code
, and
LSAPI code
are highlighted.
See history.txt for a list of bugs and changes in LSLua.
To see how LSLua may be used, with examples, see http://wiki.litestep.com.ar/Modules:LSLua
Visual C++ 2008 runtimes are required. If Litestep cannot load the module, click here.
See the Lua 5.1 manual for a quick reference on using Lua. See also the book Programming in Lua. Code snippets and general information can be found at the lua-users wiki. Finally, for more specific questions not covered by those resources, feel free to ask for help in #lua on irc.freenode.net
To load LSLua, put a line resembling *NetLoadModule lslua-0.7
load lslua.dll
in your theme.rc. The
load lslua.dll
part is important, since,
due to restrictions in NetLoadModule, all of the modules that come with
LSLua must have a .dll extension for NetLoadModule to unpack them to the
correct place.
LSLua can be loaded threaded, but be aware that this can produce strange behavior. Litestep has no means of syncronisation between modules and you will most likely use lslua to interact with other modules. In most cases lua's coroutines will be the better choice over loading the module threaded.
*LuaFile <filename>
Executes the given file. This registers any functions that are declared,
and executes any statements not declared in a function. Any function
whose name begins with bang_
is also registered as a bang
command, named with the rest of the function name. For example, the
function bang_test
would be registered as
!test
. Bang functions take one optional string
argument consisting of the entire argument string passed to them.
*LuaBinaryModuleDir <directory>
Declares a directory to be added to the search path for binary modules
(package.cpath
). Uses an extension of .dll.
*LuaScriptModuleDir <directory>
Declares a directory to be added to the search path for Lua script
modules (package.path
). Uses an extension of .lua or
.lua.dll.
*LuaModuleDir <directory>
Equivalent to both of *LuaBinaryModuleDir
and
*LuaScriptModuleDir.
LSLuaErrorFile <file>
If set errors in lua scripts will be dumped to the <file> instead of shown via MessageBox.
!LuaExec <lua chunk>
Executes the argument as a Lua chunk.
LSLua defines the global table lslua
which contains some
important functions and variables.
lslua.message_box (text, title)
Creates a message box with text of text and optional title of title.
Quotes do work correctly, unlike !alert
.
lslua.exec (str)
Executes str
as a command, like LSXCommand or
!execute []
.
Uses LSExecute()
.
lslua.res ()
Returns a table such that lslua.res().x
is the x resolution,
lslua.res().y
is the y resolution, and
lslua.res().bpp
is the bits per pixel.
lslua.mouse ()
Returns x,y
such that x
is the x
coordinate of the mouse and y
is the y
coordinate of the mouse.
lslua.milli ()
Returns the current number of milliseconds since the last second (use
os.date
to get the rest of the time information).
lslua.version
a string containing the lslua version.
lslua.get_evar (name)
Get an evar's value in memory, not file. Returns a string, or
nil
if evar is not defined. Similar to what you expect
$name$
would give.
Uses GetRCString()
.
Note: the preferred way to use this function is through the evar module.
lslua.get_line (evar_name)
Get an evar's raw value in memory, not file. Returns a string, or
nil
if evar is not defined. Similar to get_evar but does not
return first token.
Uses GetRCLine()
.
lslua.set_evar (name, value)
Set an evar's value in memory, not file.
Uses LSSetVariable()
.
Note: the preferred way to use this function is through the evar module.
lslua.rc_lines (prefix, file)
Get lines with given prefix from rc file. Use empty string for prefix to return all lines. If file not specified, defaults to settings already loaded in memory. Returns a table of strings.
Uses LCReadNextCommand()
.
lslua.init
A user defined value that is called at the very end of module load, so that bangs are registered. It is also executed in a coroutine, so timers should work.
lslua.quit
Similar to lslua.init
,
but is called when lslua is unloaded.
LSLua comes with eight modules designed to make certain tasks easier. To
use one, include the line require "<modulename>"
at
the top of your Lua script.
The args module defines some useful argument parsing functions.
args.strjoin (table, sep)
Takes two arguments: a table of strings, and a string to use as the
separator. Returns a string containing all of the elements of the table
concatenated together, with elements separated by the separator string
passed as the second argument. For example, args.strjoin( { "this",
"is", "a", "test" }, " " ) == "this is a test"
args.strsplit (string, sep)
Takes two arguments: a string, and a delimiter (a separator). It splits
the string up into a table of substrings based on the delimiter, and
returns that table. For example, args.strsplit( "this is a test", "
" ) == { "this", "is", "a", "test" }
args.mstrsplit (string, sep)
The same as args.strsplit
,
except it returns the results as multiple return values rather
than as a table.
args.qsplit (string [, delimiters [, leftquotes [, rightquotes
]]])
Takes between 1 and 4 arguments, some of them optional. first argument is
a string, the second is a table of strings to use as delimiters, and the
third and fourth are tables of strings to use as left and right quotes,
respectively. If the fourth argument is omitted, it defaults to the same
as the third, and if they are both omitted, they default to { "\"",
"'" }
. If the second argument is omitted, it defaults to { "
" }
. If any of the second, third, or fourth arguments are strings,
they are automatically converted to tables holding those strings. This
function splits the string into substrings based on the delimiter like
args.strsplit
does,
but it takes into account quote characters as well. For example,
args.qsplit( "this is a 'string with quotes'" ) == { "this", "is", "a", "string with quotes" } args.qsplit( "%{hello},%{world}", ",", "%{", "}" ) == { "hello", "world" } args.qsplit( "[this is][a test]", "", "[", "]" ) == { "this is", "a test" }
args.mqsplit (string [, delimiters [, leftquotes [, rightquotes
]]])
The same as args.qsplit
,
except it returns the results as multiple return values rather than
as a table.
The evar module allows access to and (re)assignment of LiteStep evars.
evar.toboolean (evar)
Takes one argument, a string for an evar's name. It returns a boolean
evaluating the given evar as a boolean as how LiteStep core would in RC
'scripting'/preprocessing: It returns false
for an evar
whose value is one of these strings: "0"
,
"false"
, "off"
, or "no"
. Otherwise
it returns true
.
If for some reason you need to access the evar named "toboolean", access it with a different casing, like "ToBoolean".
The evar table itself can be indexed to access the values of evars. For
example, evar.LiteStepDir == evar[ "LiteStep" .. "Dir" ] --is
"C:\LiteStep\" (on my system)
.
The result is nil
for both undefined evars and those evars
previously set to nil
through the evar table (a magic value
is replaced with nil
).
Keys of the evar table can be assigned to; doing so will set an evar's
value. tostring()
is applied to this value. For example,
evar.nameOfEvar = 13
.
Setting an evar to nil
this way will actually set the evar
to a magic value.
Notes on evar access and assignment and why a magic
value for nil
:
There is no way (aside from !reload
or
!recycle
or restarting LS) to undefine an evar,
so the evar module has its own notion of 'undefined'; It does so using
its own magic value.
So it makes no sense to set an evar to nil
, because evars
are just key-value pairs where both key and value are strings --omitting
one or the other or both makes no sense.
The choice to handle nil
specially is because of the
addition of evar.toboolean()
;
nil
should be recognized as false
;
why not handle nil
in assignment as well?
To avoid this issue, don't associate the idea that an evar can hold
nil
.
The evarutil module provides functions to handle evars. You can use this module to save evars to a file.
evarutils.savevar(filename, varname, value [, comment])
Sets all occurances of varname
in file filename
to value
and appends the specified comment if it is provided.
evarutils.getvalue(filename, varname)
Reads file filename
and tries to find varname
. Returns the var's value or nil
evarutils.deletevar(filename,varname)
Removes all occurances of varname
from file filename
.
evarutils.config
evarutils.config
provides simple shortcuts for reading and writing config files. You can handle your Theme's settings in a very simple way with this.
The syntax for working with the config object is
evarutils.config.[<relative folders>.*]<filename>.<evarname> = <value>
The file path is constructed from evar.ThemeDir .. <relative folders> .. <filename> .. ".rc"
.
Example:
First, create a config object for the file you want to save your theme's settings to:
cfg = evarutils.config.Settings.themevars
You can get the full path by calling tostring on the object:
path = tostring( cfg ) ---> path = "C:\Litestep\Themes\Mytheme\Settings\themevars.rc"
Now, If you want to save a evar, simply index the config object:
cfg.MySettingOne = "'Hello file!'" ---> Writes "MySettingOne 'Hello file!'" to xx\Settings\themevars.rc.
To read a setting from the file use
setting = cfg:get('Setting') ---> Looks for a line like "Setting value" in the file and returns value
Delete a settings from the file:
cfg:delete('Setting') ---> Removes Setting from the file
Toggle a boolean evar in the file:
cfg:toggle('Setting') ---> interprets Setting as a boolean and inverts it.
This is designed to emulate the textedit.dll/xTextedit.dll modules in Lua. It can search through files, replace lines, insert lines, delete lines, etc. The main difference is that this module uses Lua pattern matching instead of standard regexes like textedit.dll does.
If you just want to read/write evars in a file, use the evarutils module instead!
textedit.append (filename, str)
Adds str
as a line at the end of the file
filename
.
textedit.insert (filename, pattern, str, mode)
Searches through the file filename
for lines matching
pattern
, and inserts str
there. 'There' is
determined by part of the string mode
. The mode
string can be any combination of the letters g
,
i
, b
, and G
. g
means
'global', and means that the function will be applied to every matching
line in the file. i
means case insensitive, which should be
self-explanitory. b
means before, and only applies to
insert. If b
is given, str
will be inserted
before the matching line, otherwise it will be inserted after.
G
means line global, and only applies for
textedit.replace()
.
It means that
textedit.replace()
should replace each match on a given line, instead of the first.
Returns the number of insertions made.
textedit.delete (filename, pattern, mode)
Deletes lines in filename
that match pattern
,
following the mode rules from
textedit.insert()
. Returns the
number of deletions made.
textedit.replace (filename, pattern, replace_pattern, mode)
Searches the file filename
for lines that match
pattern
and replaces pattern
with
replace_pattern
on those lines. Captures and stuff like that
from string.gsub()
are all valid here. Returns the number of
times it replaced pattern
.
textedit.find (filename, pattern, mode)
Searches filename
for pattern
, and returns
either the number of the first line that matches, or a table containing
all lines that match if the mode string contains g
.
textedit.delete_line (filename, line_num)
Deletes line number line_num
from the file
filename
. It returns true
if the line was
successfully deleted and false
otherwise.
textedit.insert_line (filename, str, line_num, before)
Inserts str
into the file filename
either
before line_num
if before
is true
,
or after line_num
if before
is
false
. Returns true
if the insertion was
successful and false
otherwise.
textedit.get_line (filename, line_num)
Returns a string containing the contents of line line_num
in
file filename
.
This module can abstracts Litestep modules as Lua objects, bringing all the greatness of OOP to scripting in litestep. It currently supports Andymon's xModules and Timers, but can be extended very easily.
Basically this means that evars are mapped to class attributes and bangs are mapped to class methods, providing simple and direct access to them, without having to construct bangs manually from strings and running them with lslua.exec. The concrete wappers for modules are construced by a maze of clever metatables on access and are cached. Don't worry, there are examples below :-)
myObject = lsmodule.<module name>.<module instance name>
You always have to give a instance name, even for modules that can only exists once ( like xtray ).
traymodule= lsmodule.xtray --represents the xtray module ( which you can :unload() for example)
mytray= lsmodule.xtray.xtray --represents the xtray ( which you can :move() for example)
Now any of the wrapped module's bangs can be accessed with simple names ( "<module name><bang>" becomes "<bang>" ). If the called method has side effects (i.e. "!Move" changes the x and y position) all changed attributes are set accordingly.
myObject:<simple bang name>( <bang parameter1> , < more bangparameters>, .. )
Evars are also accessible directly through the wrapper with simple names ( "<module instance><evar>" becomes "<evar>" ).
value = myObject.<simple evar name>
"Current" Evars are used first, so myxLabel.x
tries to return $labelCurrentX$ before looking for $labelx$
Now that the modules are wrapped in lua objects it is easy ( and short!) to do pretty much anything with them.
require "lsmodule" -- load the module
function bang_hello()
-- our object ... it doesnt matter that the label does not exists, it doesn't even have a name we know!
local hellolabel = lsmodule.xlabel[lsmodule.getname()]
-- but it has to look somehow:
hellolabel.paintingmode = ".singlecolor"
hellolabel.colors = "#ff3322" -- i hope its not ugly
hellolabel.fontheight = 22
hellolabel.alwaysontop = true
hellolabel.starthidden = "True" --so it doesnt show immidiatly after we created it
hellolabel.text = '"Hello world of Litestep!"' -- setting evars with spaces takes extra quotes!
hellolabel.width = 400
hellolabel.height = 80
-- lets have it do stuff ... like ... count up when clicked!
local x = 0
local count = function( y ) -- a short lua function that counts how often it was called
x=x+1
if x==1 then lslua.message_box("Hello, nice to meet you!")
elseif x > y then lslua.message_box("Give up already!!") -- functions give up too
else lslua.message_box(("You can stop calling me now, you did that %i times already!"):format(x)) end
end
-- a callback is a litestep string that will run lua code! In this case it will run "count( 5 )" every time
hellolabel.OnLeftClick = lsmodule.callback( count, 5)
-- the label is set up, lets create it
hellolabel:create() -- now it exists, but still hidden
-- position it
local xmouse, ymouse = lslua.mouse() --get the current mouse pos
hellolabel:move( xmouse-(hellolabel.width/2), ymouse-(hellolabel.height/2) ) -- center it under the mouse
hellolabel:show() -- show it
-- lets play a bit with timers, too
local timer
local ttl = 15
-- calls a function every 1s
timer = lsmodule.every("1s", function()
ttl = ttl-1
hellolabel:settext(('Hello world of Litestep!
This label will autodestruct in %i secounds!'):format(ttl))
end
)
-- a 15 sec timer that will destroy the label and stop the update timer
lsmodule.after( "15s", function() timer:stop() hellolabel:destroy() end):start() -- start it first
timer:start() -- start the update timer
end
You can copy this code to a lua file and try it out right away. Simply run "!hello" ( more than once too!) and watch how nicely it all works together :-).
lsmodule.getname()
myNewObject = lsmodule.xlabel[lsmodule.getname()]
myNewObject.addtogroup = "some_basic_settings"
myNewObject:create()
lsmodule.callback(function, *args)
local mylabel = lsmodule.xlabel.mylabel -- this shall recieve a callback
local hellofunc = function( x ) lsmodule.message_box( "Hello from the callback\nThe event was: " .. tostring(x)" end
mylabel.onenter = lsmodule.callback( hellofunc , "onenter")
mylabel.onleave = lsmodule.callback( hellofunc , "onleave")
mylabel.onclick = lsmodule.callback( mylabel.moveby , mylabel, 10, 0) -- member functions ( normally called with a ':' ) need themself as the first argument
lsmodule.after( timeout, function, *args)
local timer = lsmodule.after("10s", hellofunc, "a timer called!")
timer:start()
lsmodule.every( timeout, function, *args)
local timer = lsmodule.after("3s", lslua.message_box, "STOP! HAMMERTIME!")
timer:start()
NOTE: Both lsmodule.every and lsmodule.after return a *new* timer object (as in lsmodule.timer.*) every time they are called. You have to start the timer yourself! Also the timer module supports only *100* timers, and they cannot be destroyed! So make sure you store your timers somewhere and reuse them (update
lsmodule.unserialize( string )
lsmodule.<module name>.<module instance name>:serialize() --> "lsmodule.module_name.module_instance" (a string)
lsmodule.unserialize("lsmodule.module_name.module_instance") --> lsmodule.<module name>.<module instance name> (a object)
lsmodule.sortby( attribute )
and lsmodule.revsortby( attribute )
myobjects = { obj1, obj2, obj2 } -- table with all object you want to sort
table.sort( myobjects, lsmodule.sortby('x') ) -- sort by x positon
table.sort( myobjects, lsmodule.revsortby('y') ) -- reverse sort by y positon
<module>.version
<module>:load()
<module>:unload()
<instance>.varfile
Changes to a instance can be automatically saved to a file if the instance has a varfile
attribute with the path to a file:
<module instance name>Varfile "X:/path/to/file"
or mylabel.varfile = evar.themedir .. "mylabelvarfile.rc"
mylabel.settext( "save me!") -- Updates 'mylabelvarfile.rc' with SomeLabeltext "Save me!"
taskbar.Alwaysontop = False -- Updates 'mylabelvarfile.rc' with xTaskbarAlwaysonTop false
<instance>:dockto(other, side, offset, steps,tim)
Instances can dock to others ( if they can move )
obj:dockto(other, side, offset, steps,tim) -- other = some object, side = "left" / "right" / top" / "bottom"
<instance>:covers(x,y)
Returns if a instance covers a specific point with
mylabel:covers(100, 200) -- true/false
If you want to use additional modules, all you have to do is create a new bangset. Imagine the iNsAnE module uses strange bangs, so you want nicer commands.


Hack In The North has always been pushing the envelope on making the developer environment a more inclusive one, especially for women developers. The last edition of Hack in The North saw Diversity sponsors and partners such as GitLab and Women Who Code. Further, there were special slots for all-girls teams and special prizes for best women team.
This spirit of inclusivity, especially after the abolition of section 377, is going to see a lot of growth in the next editions of Hack In The North. Stay tuned for more updates on our diversity initiatives!


Not an academic competition question, but one of the most difficult queries Brian Rostron has ever faced. Allow him to explain:
Last summer I was working in a T-shirt factory. I pulled shirts for orders and then took them to be packed and shipped. Most of the packers were a surly bunch, but one of them liked to talk to me a lot. I assumed that he was just naturally friendly. One day I was climbing on some boxes to get some shirts. I knocked my pen to the floor, and the cheerful packer picked it up. He walked over to me, looking to make sure that no one else was around. Then he said, "I've been meaning to ask you this. Are you like me?" Somewhat taken aback, I decided at that moment that if anyone asked me that question, regardless of how similar they were to me, I would say no. I replied, "Uh, I don't think so." He shrugged and walked away, and then turned around and came back. "Maybe I should make myself a little clearer," he said. "I like guys." I responded, "Then you're definitely not like me." He took this well and said finally, "That's fine. It's just that I've been wondering for a couple of weeks and I had to know." After that, he never talked to me again. I told this story at our first team meeting of the year, and then later Mike Dershewitz talked about his job experience. When I asked him if any male co-workers had shown romantic interest in him over the summer, he looked puzzledly at me and said "No." Then I replied, "Hmm. That surprises me." Mike got this really hurt and confused look on his face. It was adorable.
John Edwards' emphatic reply to Phil O'Donoghue's lack of clarity in 70's blaxploitation film heroes. At CBI nationals in 1997, we were waiting around because of some unexplained delay before our match with Florida. Behind the room we were playing in, there was a partition and then another room set up with tables and a microphone. Phil and John went back there to screw around.  John then said, "Phil, you dumbass! It's John Shaft." Moments later, a shaken Phil O'Donoghue was only left to mutter, "You know I really thought that it was Superfly." Return to the current UVA lexicon.


Bibliotecas do Play
The play.libs
package contains several useful libraries that will help you to achieve common programming tasks.
Most of these libraries are simple helpers that are really straightforward to use:
- Codec: Utilities to encode and decode data.
- Crypto: Cryptographics utilities.
- Expression: Evaluate dynamic expressions.
- F: Programação funcional com java.
- Files: File system manipulation helpers.
- I18N: Internationalização helpers.
- IO: Stream manipulation helpers.
- Images: Image manipulation utilities.
- Mail: E-mail functions.
- MimeTypes: Dealing with MIME types.
- OAuth: OAuth client protocol.
- OAuth2: OAuth2 client protocol.
- OpenID: OpenID client protocol.
- Time: Time and duration utilities.
- WS: Powerful Cliente Web Service.
- XML: Loading XML structures.
- XPath: Parsing XML using XPath.
The following sections provide more information about the most important libraries.
Parsing XML using XPath
XPath is probably the easiest way to parse an XML document without having to use code generation tools. The play.libs.XPath
library offers all the needed primitives to efficiently achieve this task.
The XPath
operations operate on all org.w3.dom.Node
types:
org.w3.dom.Document xmlDoc = … // retrieve a Document somewhere
for(Node event: XPath.selectNodes("events//event", xmlDoc)) {
String name = XPath.selectText("name", event);
String data = XPath.selectText("@date", event);
for(Node place: XPath.selectNodes("//place", event)) {
String place = XPath.selectText("@city", place);
…
}
…
}
Cliente Web Service
The play.libs.WS
provides a powerful HTTP client. Under the hood it uses Async HTTP client.
Making a request is easy:
HttpResponse res = WS.url("http://www.google.com").get();
Once you have an HttpResponse
object you can access all the response properties.
int status = res.getStatus();
String type = res.getContentType();
You can also retrieve the body content in several content types:
String content = res.getString();
Document xml = res.getXml();
JsonElement json = res.getJson();
InputStream is = res.getStream();
You can also use the async API to make HTTP requests in a non-blocking way. Then you will receive a Promise<HttpResponse>
. Once redeemed, you can use the HttpResponse
as usual:
Promise<HttpResponse> futureResponse = WS.url(
"http://www.google.com"
).getAsync();
Programação funcional com java
The play.libs.F
library provide several useful constructs coming from functional programming. These constructs are used to handle complex abstraction cases. For those that are accustomed to functional programming we provide:
Option<T>
(a T value that can be or not set)Either
(contains either a A value or a B value)Tuple
(contains both A and B values)
Option<T>
, Some<T>
and None<T>
When you write a function that may not return a result in some cases (e.g. a find
method), a common (bad) Java pattern is to return null
when there is no result. This practice is dangerous because the function return type does not clearly shows that it may not return an object and it has been recognized by the nullable references inventor to be a “billion-dollar mistake”.Option<T>
is an elegant solution to this problem: instead of returning an object of type T
, the function returns an Option<T>
. If the function succeeds, it returns an object of type Some<T>
(wrapping the real result), otherwise an object of type None<T>
, which both are subtypes of Option<T>
.
Here is an example:
/* Safe division (will never throw a runtime ArithmeticException) */
public Option<Double> div(double a, double b) {
if (b == 0)
return None();
else
return Some(a / b);
}
Here is a way to use this function:
Option<Double> q = div(42, 5);
if (q.isDefined()) {
Logger.info("q = %s", q.get()); // "q = 8.4"
}
But there is a more convenient syntax to use it, leveraging the fact that Option<T>
implements Iterable<T>
:
for (double q : div(42, 5)) {
Logger.info("q = %s", q); // "q = 8.4"
}
The body of the for loop is be executed once, only if the div
function succeeded.
Tuple
The handy Tuple
class wraps two objects of type A
and B
. You can retrieve the objects using the _1
and _2
fields, respectively. For example:
public Option<Tuple<String, String>> parseEmail(String email) {
final Matcher matcher = Pattern.compile("(\\w+)@(\\w+)").matcher(email);
if (matcher.matches()) {
return Some(Tuple(matcher.group(1), matcher.group(2)));
}
return None();
}
Then:
for (Tuple<String, String> email : parseEmail("foo@bar.com")) {
Logger.info("name = %s", email._1); // "name = foo"
Logger.info("server = %s", email._2); // "server = bar.com"
}
The T2
class is an alias for Tuple
. To handle tuples of 3 elements use the T3
class, and so on up to T5
.
Pattern Matching
Several times we’ve felt that we needed pattern matching in Java. Unfortunately Java does not have built-in pattern matching, and because of the lack of functional constructs, it is difficult to add it as a library. Anyway we’ve worked on a solution that is not so bad.
Our idea was to use the latest ‘for loop’ syntax to achieve basic pattern matching for Java. Pattern matching must both check if your object matches the required conditions and extract the interesting value. The Pattern matching library for Play is part of the play.libs.F
library.
Let’s see a simple example; you have a reference of type Object and you want to check that it is a string that starts by ‘command:’.
The standard way would be:
Object o = anything();
if(o instanceof String && ((String)o).startsWith("command:")) {
String s = (String)o;
System.out.println(s.toUpperCase());
}
Using the Play pattern matching library, you can write it as:
for(String s: String.and(StartsWith("command:")).match(o)) {
System.out.println(s.toUpperCase());
}
The for loop is executed once, only if the condition is met, and it automatically extracts the String value without the need for casting. Because there is no explicit cast, everything is type-safe, and checked by the compiler.
Promises
A Promise
is Play’s custom Future
type. In fact a Promise<T>
is also a Future<T>
so you can use it as a standard Future
. But it has also a very interesting property: the ability to register callback using onRedeem(…)
that will be called as soon as the promised value is available.
Promise
instances are used everywhere in Play in place of Future
instances (for Jobs, WS.async
, etc…).
Promises can be combined in several ways. For example:
Promise p = Promise.waitAll(p1, p2, p3)
Promise p = Promise.waitAny(p1, p2, p3)
Promise p = Promise.waitEither(p1, p2, p3)
OAuth
OAuth is an open protocol for secure API authorization, using a simple and standard approach, from desktop and web applications.
Two different specifications exist: OAuth 1.0 and OAuth 2.0. Play provides libraries to connect as a consumer to services proposing either of these specifications.
The general process is the following:
- Redirect the user to the provider’s authorization page
- After the user grants authorization, he is redirected back to your server along with an unauthorized token
- Your server exchanges the unauthorized token with an access token specific to the current user, that needs to be saved in order to perform requests to the service. This step is done as server-to-server communication.
The Play framework takes care of most of the process.
OAuth 1.0
The OAuth 1.0 functionality is provided by the play.libs.OAuth
class and is based on oauth-signpost. It is used by services such as Twitter or Google
To connect to a service, you need the create a OAuth.ServiceInfo instance using the following information, obtained from the service provider:
- Request token URL
- Access token URL
- Authorize URL
- Consumer key
- Consumer secret
The access token can be retrieved this way:
public static void authenticate() {
// TWITTER is a OAuth.ServiceInfo object
// getUser() is a method returning the current user
if (OAuth.isVerifierResponse()) {
// We got the verifier;
// now get the access tokens using the request tokens
OAuth.Response resp = OAuth.service(TWITTER).retrieveAccessToken(
getUser().token, getUser().secret
);
// let's store them and go back to index
getUser().token = resp.token; getUser().secret = resp.secret;
getUser().save()
index();
}
OAuth twitt = OAuth.service(TWITTER);
Response resp = twitt.retrieveRequestToken();
// We received the unauthorized tokens
// we need to store them before continuing
getUser().token = resp.token; getUser().secret = resp.secret;
getUser().save()
// Redirect the user to the authorization page
redirect(twitt.redirectUrl(resp.token));
}
Calls can now be done by signing the requests using the token pair:
mentions = WS.url(url).oauth(TWITTER, getUser().token, getUser().secret).get().getString();
While the example doesn’t check for errors, in production you should. The OAuth.Response object holds an error field that is non-null when an error occurred. Most likely it could be that the user didn’t grant you access, that the provider is down or buggy.
The full example usage is available in samples-and-tests/twitter-oauth
.
OAuth 2.0
OAuth 2.0 is much simpler than OAuth 1.0 because it doesn’t involve signing requests. It is used by Facebook and 37signals.
Functionality is provided by play.libs.OAuth2
.
To connect to a service, you need the create a OAuth2 instance using the following information, obtained from the service provider:
- Access token URL
- Authorize URL
- Client ID
- Secret
public static void auth() {
// FACEBOOK is a OAuth2 object
if (OAuth2.isCodeResponse()) {
// authUrl must be the same as the retrieveVerificationCode call
OAuth2.Response response = FACEBOOK.retrieveAccessToken(authUrl);
// null if an error occurred
String accessToken = response.accessToken;
// null if the call was a success
OAuth2.Error = response.error;
// Save accessToken, you will need it to request the service
index();
}
// authUrl is a String containing an absolute URL where the service
// should redirect the user back
// This will trigger a redirect
FACEBOOK.requestVerificationCode(authUrl);
}
Once you have the access token associated with the current user, you can use it to query the service on behalf of the user:
WS.url(
"https://graph.facebook.com/me?access_token=%s", access_token
).get().getJson();
The full example usage is available in samples-and-tests/facebook-oauth2
.
OpenID
OpenID is an open and decentralized identity system. You can easily accept new users in your application without having to keep specific user information. You just have to keep track of authorized users through their OpenID.
This example provides a high-level view of how OpenID authentication can be used within a Play application:
- For each request, check if the user is connected
- If not, display a page where the user can submit his OpenID
- Redirect the user to the OpenID provider
- When the user comes back, get the verified OpenID and save it in the HTTP session.
The OpenID functionality is provided by the play.libs.OpenID
class.
@Before(unless={"login", "authenticate"})
static void checkAuthenticated() {
if(!session.contains("user")) {
login();
}
}
public static void index() {
render("Hello %s!", session.get("user"));
}
public static void login() {
render();
}
public static void authenticate(String user) {
if(OpenID.isAuthenticationResponse()) {
UserInfo verifiedUser = OpenID.getVerifiedID();
if(verifiedUser == null) {
flash.error("Oops. Authentication has failed");
login();
}
session.put("user", verifiedUser.id);
index();
} else {
if(!OpenID.id(user).verify()) { // will redirect the user
flash.error("Cannot verify your OpenID");
login();
}
}
}
And the login.html
template:
#{if flash.error}

${flash.error}

#{/if}
<form action="@{Application.authenticate()}" method="POST">
What’s your OpenID?
<input type="text" name="user" id="user" />
<input type="submit" value="login…" />
</form>

And finally the routes
definitions:
GET / Application.index
GET /login Application.login
* /authenticate Application.authenticate
Continuing the discussion
Now we’ll check how to perform operations outside any HTTP request using Ansynchronous Jobs.


- Download the Gulp devtools extension for Chrome Developer Tools from the Chrome Web Store.
- If not already installed, run npm install -g gulp-devtools
- Export gulp from your gulpfile.js by adding module.exports = gulp;
- Run gulp-devtools
in a directory with a gulpfile!
- Open Chrome Dev tools, find the Gulp tab. Your gulp tasks should now be accessible from Chrome.