\section{GATE and Groovy}

\subsection{Introduction to Groovy}

% allow @something@ for short snippets of inline groovy
\lstMakeShortInline[language=groovy]@

\begin{frame}
\frametitle{Groovy}
\begin{itemize}
\item Dynamic language for the JVM
\item Groovy scripts and classes compile to Java bytecode -- fully
  interoperable with Java.
\item Syntax very close to regular Java
\item Explicit types optional, semicolons optional
\item Dynamic dispatch -- method calls dispatched based on runtime type rather
  than compile-time.
\item Can add new methods to existing classes at runtime using \emph{metaclass}
  mechanism
\item Groovy adds useful extra methods to many standard classes in
  \texttt{java.io}, \texttt{java.lang}, etc.
\end{itemize}
\end{frame}

\begin{frame}[t,fragile]
\frametitle{Groovy example}
Find the start offset of each absolute link in the document.
\begin{uncoverenv}<+->
\begin{lstlisting}[language=groovy]
def om = document.getAnnotations("Original markups")
om.get('a').findAll { anchor ->
  anchor.features?.href =~ /^http:/
}.collect { it.startNode.offset }
\end{lstlisting}
\end{uncoverenv}
\begin{itemize}[<+->]
\item @def@ keyword declares an untyped variable
\item but dynamic dispatch ensures the @get@ call goes to the right class
  (@AnnotationSet@).
\item @findAll@ and @collect@ are methods added to @Collection@ by Groovy
  \begin{itemize}
  \item \url{http://groovy.codehaus.org/groovy-jdk} has the details.
  \end{itemize}
\item @?.@ is the \emph{safe navigation} operator -- if the left hand operand
  is @null@ it returns @null@ rather than throwing an exception
\end{itemize}
\omitfromhandout<-5>
\end{frame}

\begin{frame}[t,fragile]
\frametitle{Groovy example}
Find the start offset of each absolute link in the document.
\begin{uncoverenv}<+->
\begin{lstlisting}[language=groovy]
def om = document.getAnnotations("Original markups")
om.get('a').findAll { anchor ->
  anchor.features?.href =~ /^http:/
}.collect { it.startNode.offset }
\end{lstlisting}
\end{uncoverenv}
\begin{itemize}[<+->]
\item @=~@ for regular expression matching
\item unified access to JavaBean properties -- @it.startNode@ shorthand for
  @it.getStartNode()@
\item and @Map@ entries -- @anchor.features.href@ shorthand for
  @anchor.getFeatures().get("href")@
\item @Map@ entries can also be accessed like arrays, e.g. @features["href"]@
\end{itemize}
\omitfromhandout<-4>
\end{frame}

\begin{frame}[fragile]
\frametitle{Closures}
Parameter to @collect@, @findAll@, etc. is a \emph{closure}
\begin{itemize}
\item like an anonymous function (JavaScript), a block of code that can be
  assigned to a variable and called repeatedly.
\item Can declare parameters (typed or untyped) between the opening brace and
  the @->@
\item If no explicit parameters, closure has an implicit parameter called
  @it@.
\item Closures have access to the variables in their containing scope (unlike
  Java inner classes these do not have to be @final@).
\item The return value of a closure is the value of its last expression (or an
  explicit @return@).
\item Closures are used all over the place in Groovy
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{More Groovy Syntax}
\begin{itemize}
\item Shorthand for lists: @["item1", "item2"]@ declares an @ArrayList@
\item Shorthand for maps: @[foo:"bar"]@ creates a @HashMap@ mapping the key
  @"foo"@ to the value @"bar"@.
\item Interpolation in \emph{double-quoted} strings (like Perl):
  @"There are ${anns.size()} annotations of type ${annType}"@
\item Parentheses for method calls are optional (where this is unambiguous):
  @myList.add 0, "someString"@
  \begin{itemize}
  \item When you use parentheses, if the last parameter is a closure it can go
    outside them: this is a method call with two parameters
    @someList.inject(0) { last, cur -> last + cur }@
  \end{itemize}
\item ``slashy string'' syntax where backslashes don't need to be doubled:
  @/C:\Program Files\Gate/@ equivalent to @'C:\\Program Files\\Gate'@
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Operator Overloading}
\begin{itemize}
\item Groovy supports operator overloading cleanly
\item Every operator translates to a method call
  \begin{itemize}
  \item @x == y@ becomes @x.equals(y)@ (for reference equality, use @x.is(y)@)
  \item @x + y@ becomes @x.plus(y)@
  \item @x << y@ becomes @x.leftShift(y)@
  \item full list at \url{http://groovy.codehaus.org}
  \end{itemize}
\item To overload an operator for your own class, just implement the method.
\item e.g. List implements @leftShift@ to append items to the list:
  @['a', 'b'] << 'c' == ['a', 'b', 'c']@
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Groovy in GATE}
\begin{itemize}
\item Groovy support in GATE is provided by the \texttt{Groovy} plugin.
\item Loading the plugin
  \begin{itemize}
  \item enables the Groovy scripting console in GATE Developer
  \item adds utility methods to various GATE classes and interfaces for use
    from Groovy code
  \item provides a PR to run a Groovy script.
  \item provides a \emph{scriptable controller} whose execution strategy is
    determined by a Groovy script.
  \end{itemize}
\end{itemize}
\end{frame}

\subsection{Scripting GATE Developer}

\begin{frame}[fragile]
\frametitle{Scripting GATE Developer}
\begin{columns}
  \begin{column}{0.5\textwidth}
    \begin{itemize}
    \item Groovy provides a Swing-based \emph{console} to test out small
      snippets of code.
    \item The console is available in the GATE Developer GUI via the Tools menu.
      To enable, load the \texttt{Groovy} plugin.
    \end{itemize}
  \end{column}
  \begin{column}{0.5\textwidth}
    \includegraphics[width=\textwidth]{img/groovy/groovy-console}
  \end{column}
\end{columns}
\end{frame}

\begin{frame}[fragile]
\frametitle{Imports and Predefined Variables}
The GATE Groovy console imports the same packages as JAPE RHS actions:
\begin{itemize}
\item @gate@, @gate.annotation@, @gate.util@, @gate.jape@ and
  @gate.creole.ontology@
\end{itemize}
The following variables are implicitly defined:
\begin{description}
\item[corpora] a list of loaded corpora LRs (@Corpus@) 
\item[docs] a list of all loaded document LRs (@DocumentImpl@) 
\item[prs] a list of all loaded PRs 
\item[apps] a list of all loaded Applications (@AbstractController@)
\end{description}
\end{frame}

\begin{frame}[fragile]
\frametitle{\color{gate-dark-green} Exercise 1: The Groovy Console}
\begin{itemize}
\item Start the GATE Developer GUI
\item Load the \texttt{Groovy} plugin
\item Select Tools $\rightarrow$ Groovy Tools $\rightarrow$ Groovy Console
\item Experiment with the console
\item For example to tokenise a document and find how many ``number'' tokens it
  contains:
\end{itemize}
\begin{lstlisting}[language=groovy, breaklines, basicstyle=\scriptsize\ttfamily]
doc = Factory.newDocument(new URL('http://gate.ac.uk'))
tokeniser = Factory.createResource('gate.creole.tokeniser.DefaultTokeniser')
tokeniser.document = doc
tokeniser.execute()
tokens = doc.annotations.get('Token')
tokens.findAll { it.features.kind == 'number' }.size()
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{\color{gate-dark-green} Exercise 1: The Groovy Console}
\begin{itemize}
\item Variables you assign in the console (without a @def@ or a type
  declaration) remain available to future scripts in the same console.
\item So you can run the previous example, then try more things with the
  @doc@ and @tokens@ variables.
\item Some things to try:
  \begin{itemize}
  \item Find the names and sizes of all the annotation sets on the document
    (there will probably only be one named set).
  \item List all the different @kind@s of token
  \item Find the longest word in the document
  \end{itemize}
\end{itemize}
\end{frame}

\ifsolutions
\addtocounter{framenumber}{-1}\framenumbersfalse
\begin{frame}[fragile]
\omitfromhandout
\frametitle{\color{gate-dark-green} Exercise 1: Solution}
Some possible solutions (there are many\ldots)
\begin{lstlisting}[language=groovy, texcl]
// Find the annotation set names and sizes
doc.namedAnnotationSets.each { name, set ->
  println "${name} has size ${set.size()}"
}

// List the different kinds of token
tokens.collect { it.features.kind }.unique()

// Find the longest word
tokens.findAll {
  it.features.kind == 'word'
}.max { it.features.length.toInteger() }
\end{lstlisting}
\end{frame}
\framenumberstrue
\fi

\begin{frame}[fragile]
\frametitle{Groovy Categories}
\begin{itemize}
\item In Groovy, a class declaring static methods can be used as a
  \emph{category} to inject methods into existing types (including interfaces)
\item A static method in the category class whose first parameter is a
  @Document@:
  @public static SomeType foo(Document d, String arg)@
\item<+-> \ldots becomes an instance method of the @Document@ class:
  @public SomeType foo(String arg)@
\item The @use@ keyword activates a category for a single block
\item To enable the category globally: @TargetClass.mixin(CategoryClass)@
\end{itemize}
\end{frame}

% To mix it in everywhere:
%gate.Utils.methods.findAll {
%  java.lang.reflect.Modifier.isStatic(it.modifiers) &&
%     it.parameterTypes.size() > 0
%}.collect {
%  it.parameterTypes[0]
%}.unique()*.mixin(gate.Utils)

\begin{frame}[fragile]
\frametitle{Utility Methods}
\begin{itemize}
\item The @gate.Utils@ class (mentioned in the JAPE module) contains utility
  methods for documents, annotations, etc.
\item Loading the \texttt{Groovy} plugin treats this class as a category and
  installs it as a global mixin.
\item Enables syntax like:
\end{itemize}
\begin{lstlisting}[language=groovy]
tokens.findAll {
  it.features.kind == 'number'
}.each {
  println "${it.type}: length = ${it.length()}, "
  println "  string = ${doc.stringFor(it)}"
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Utility Methods}
\begin{itemize}
\item The \texttt{Groovy} plugin also mixes in the @GateGroovyMethods@ class.
\item This extends common Groovy idioms to GATE classes
  \begin{itemize}
  \item e.g. implements @each@, @eachWithIndex@ and @collect@ for @Corpus@ to
    do the right thing when the corpus is stored in a datastore
  \item defines a @withResource@ method on @Resource@, to call a closure with a
    given resource as a parameter, and ensure the resource is deleted when the
    closure returns:
  \end{itemize}
\end{itemize}
\begin{lstlisting}[language=groovy]
Factory.newDocument(someURL).withResource { doc ->
  // do something with the document
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{Utility Methods}
\begin{itemize}
\item Also overloads the subscript operator @[]@ to allow:
  \begin{itemize}
  \item @annSet["Token"]@ and @annSet["Person", "Location"]@
  \item @annSet[15..20]@ to get annotations within given span
  \item @doc.content[15..20]@ to get the @DocumentContent@ within a given span
  \end{itemize}
\item See \texttt{src/gate/groovy/GateGroovyMethods.java} in the
  \texttt{Groovy} plugin for details.
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{\color{gate-dark-green} Exercise 2: Using a category}
In the console, try using some of these new methods:
\begin{lstlisting}[language=groovy]
tokens = doc.annotations["Token"]
tokens.findAll {
  it.features.kind == 'number'
}.each {
  println "${it.type}: length = ${it.length()}, "
  println "  string = ${doc.stringFor(it)}"
}
\end{lstlisting}
\end{frame}

\subsection{The Groovy Script PR}

\begin{frame}[fragile]
\frametitle{The Groovy Script PR}
\begin{itemize}
\item The \verb|Groovy| plugin provides a PR to execute a Groovy script.
\item Useful for quick prototyping, or tasks that can't be done by JAPE but
  don't warrant writing a custom PR.
\item PR takes the following parameters:
\end{itemize}
\begin{description}
\item[scriptURL] (init-time) The path to a valid Groovy script
\item[inputASName] an optional annotation set intended to be used as input by
  the PR
\item[outputASName] an optional annotation set intended to be used as output by
  the PR
\item[scriptParams] optional parameters for the script as a @FeatureMap@
\end{description}
\end{frame}

\begin{frame}[fragile]
\frametitle{Script Variables}
The script has the following implicit variables available when it is run
\begin{description}
\item[doc] the current document
\item[corpus] the corpus containing the current document
\item[content] the string content of the current document 
\item[inputAS] the annotation set specified by inputASName in the PRs runtime
  parameters 
\item[outputAS] the annotation set specified by outputASName in the PRs runtime
  parameters
\item[scriptParams] the parameters @FeatureMap@ passed as a runtime parameter
\end{description}
and the same implicit imports as the console.
\end{frame}

\begin{frame}[fragile]
\frametitle{Corpus-level processing}
\begin{itemize}
\item Any other variables are treated like instance variables in a PR -- values
  set while processing one document are available while processing the next.
\item So Groovy script is stateful, can e.g. collect statistics from all the
  documents in a corpus.
\item Script can declare methods for pre- and post-processing:
  \begin{itemize}
  \item \verb|beforeCorpus| called before first document is processed.
  \item \verb|afterCorpus| called after last document is processed
  \item \verb|aborted| called if anything goes wrong
  \end{itemize}
\item All three take the corpus as a parameter
\item \verb|scriptParams| available within methods, other variables not.
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Controller Callbacks Example}
Count the number of annotations of a particular type across the corpus
\begin{lstlisting}[language=groovy, texcl]
void beforeCorpus(c) {
  println "Processing corpus ${c.name}"
  count = 0
}

count += doc.annotations[scriptParams.type].size()

void afterCorpus(c) {
  println "Total ${scriptParams.type} annotations " +
      "in corpus ${c.name}: ${count}"
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{\color{gate-dark-green} Exercise 3: Using the Script PR}
\begin{itemize}
\item Write the Goldfish annotator from the UIMA section as a Groovy script
  \begin{itemize}
  \item Annotate all occurrences of the word ``goldfish'' (case-insensitive) in
    the input document as the annotation type ``Goldfish''.
  \item Add a ``numFish'' feature to each Sentence annotation giving the number
    of Goldfish annotations that the sentence contains.
  \end{itemize}
\item Put your script in the file \verb|hands-on/groovy/goldfish.groovy|
\item To test, load \verb|hands-on/groovy/goldfish-app.xgapp| into GATE
  Developer (this application contains tokeniser, sentence splitter and
  goldfish script PR).
\item You need to re-initialize the Groovy Script PR after each edit to
  \verb|goldfish.groovy|
\end{itemize}
\end{frame}

\ifsolutions
\addtocounter{framenumber}{-1}\framenumbersfalse
\begin{frame}[fragile]
\frametitle{\color{gate-dark-green} Exercise 3: Solution}
One of many possible solutions:
\begin{lstlisting}[language=groovy]
def m = (content =~ /(?i)goldfish/)
while(m.find()) {
  outputAS.add(m.start(), m.end(),
      'Goldfish', [:].toFeatureMap())
}

def allGoldfish = outputAS["Goldfish"]
inputAS["Sentence"].each { sent ->
  sent.features.numFish = 
      allGoldfish[sent.start()..sent.end()].size()
}
\end{lstlisting}
\omitfromhandout
\end{frame}
\framenumberstrue
\fi

\begin{frame}[fragile]
\frametitle{The Scriptable Controller}
\begin{itemize}
\item @ConditionalSerialAnalyserController@ can run PRs conditionally based on
  the value of a document feature.
\item This is useful but limited; Groovy plugin's scriptable controller
  provides more flexibility.
\item Uses Groovy DSL to define the execution strategy.
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{The ScriptableController DSL}
\begin{itemize}
\item Run a single PR by using its \emph{name} as a method call
  \begin{itemize}
  \item So good idea to give your PRs identifier-friendly names.
  \end{itemize}
\item Iterate over the documents in the corpus using @eachDocument@
\item Within an @eachDocument@ closure, any PRs that implement
  @LanguageAnalyser@ get their @document@ and @corpus@ parameters set
  appropriately.
\item Override runtime parameters by passing named arguments to the PR method
  call.
\item DSL is a Groovy script, so all Groovy language features available
  (conditionals, loops, method declarations, local variables, etc.).
\end{itemize}
\url{http://gate.ac.uk/userguide/sec:api:groovy:controller}
\end{frame}

\begin{frame}[fragile]
\frametitle{ScriptableController example}
\begin{lstlisting}[language=groovy,texcl]
eachDocument {
  documentReset()
  tokeniser()
  gazetteer()
  splitter()
  posTagger()
  findLocations()
  // choose the appropriate classifier depending how many Locations were found
  if(doc.annotations["Location"].size() > 100) {
    fastLocationClassifier()
  }
  else {
    fullLocationClassifier()
  }
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
\frametitle{ScriptableController example}
\begin{lstlisting}[language=groovy,texcl]
eachDocument {
  // find all the annotatorN sets on this document 
  def annotators = 
    doc.annotationSetNames.findAll { 
      it ==~ /annotator\d+/ 
    } 

  // run the post-processing JAPE grammar on each one 
  annotators.each { asName -> 
    postProcessingGrammar( 
        inputASName: asName, 
        outputASName: asName) 
  } 

  // merge them to form a consensus set
  mergingPR(annSetsForMerging: annotators.join(';'))
}
\end{lstlisting}
\end{frame}

\subsection{Writing GATE Resource Classes in Groovy}

\begin{frame}[fragile]
\frametitle{Writing Resources in Groovy}
\begin{itemize}
\item Groovy is more than a scripting language -- you can write classes
  (including GATE resources such as @ScriptableController@) in Groovy and
  compile them to Java bytecode.
\item Compiler available via \verb|<groovyc>| Ant task in \verb|groovy-all|
  JAR.
\item In order to use GATE resources written in Groovy (other than those that
  are part of the Groovy plugin), \verb|groovy-all| JAR file must go into
  \verb|gate/lib|.
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Groovy Beans}
\begin{itemize}
\item Recall unified Java Bean property access in Groovy
  \begin{itemize}
  \item @x = it.someProp@ means @x = it.getSomeProp()@
  \item @it.someProp = x@ means @it.setSomeProp(x)@
  \end{itemize}
\item Declarations have a similar shorthand: a field declaration with no
  @public@, @protected@ or @private@ modifier becomes a private field plus an
  auto-generated public getter/setter pair.
\item But you can provide explicit setter or getter, which will be used instead
  of the automatic one.
  \begin{itemize}
  \item Need to do this if you need to annotate the setter (e.g. as a
    @CreoleParameter@).
  \item Declare the setter @private@ to get a read-only property (but not if
    it's a creole parameter).
  \end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile]
\frametitle{Example: a Groovy Regex PR}
\begin{lstlisting}[language=groovy,basicstyle=\scriptsize\ttfamily]
package gate.groovy.example

import gate.*
import gate.creole.*

public class RegexPR extends AbstractLanguageAnalyser {
  String regex
  String annType
  String annotationSetName

  public void execute() {
    def aSet = document.getAnnotations(annotationSetName)
    def matcher = (document.content.toString() =~ regex)
    while(matcher.find()) {
      aSet.add(matcher.start(), matcher.end(),
          annType, [:].toFeatureMap())
    }
  }
}
\end{lstlisting}
\end{frame}

% vim:ft=tex:
