If ag generates indices for a gerund ger , we will call ag an agenda function, and the function<EMAIL_ADDRESS>a case statement. For example:
ger=: f`g`h ag=: #@$ case=<EMAIL_ADDRESS>f=: -: g=: +: h=: *: (case 3);(case 2 3 4 5);(case i.3 4) +--------------------------+ |1.5|4 6 8 10| 0 1 4 9| | | |16 25 36 49| | | |64 81 100 121| +--------------------------+ f=: *: (case 3);(case 2 3 4 5);(case i.3 4) +------------------------+ |9|4 6 8 10| 0 1 4 9| | | |16 25 36 49| | | |64 81 100 121| +------------------------+
Certain agendas prove to be useful with a variety of gerunds: for example, the rank used above, as well as various classifications such as negative, zero, and positive; integral or fractional; real or complex; numeric or character; boxed or open; and the depth of boxing. Since indices may be negative, the result of an agenda may be negative; thus the case<EMAIL_ADDRESS>applies f if the argument is zero, g if it is positive, and h if it is negative.
Since an agenda such as the hook =<. (which tests for fractional or integral) might invoke a domain error (when the argument is character or boxed), it is often useful to extend an agenda to produce a result in such a case. If this result is _1, the corresponding function in the gerund (perhaps h=: 'ERROR'"_) may be simply appended to the normal cases. Thus, the test for integral may be defined (using adverse) as (=<.) :: _1: For example:
F=: (=<.) :: _1: F"0 x=: 0.5 _2 2 0 1 1 F 'abcd' _1
| m0=: ~. ,. #/.~ | Nub and count |
| m1=: ({.,#)/.~ | Nub and count |
| a2=: et=: :: _1: | Error in tail position |
| m3=: I=: (-:<.)et | Integral |
| m4=: C=: -.@(-:+) et | Complex |
| a5=: ep=: :: _2: | Error in penultimate position |
| m6=: S=: *ep | Signum test with error in penultimate |
| m7=: B=: -.@(-:>) :: 0: | Boxed |
| m8=: R=: #@$ | Rank |
An “or” over an agenda (that is, applying a given function for any one of several cases distinguished by the agenda) can be achieved by placing the same function in several places in the gerund. Moreover, agendas may be used in combination, as illustrated below:
c=<EMAIL_ADDRESS>Executes co if open; cb if boxed co=: -<EMAIL_ADDRESS>Minus magnitude if real; conjugate cb=: ]`(|.&.>)`(|:&.>)@.(R@>) Reverse if opened is list; transpose c <i. 2 4 if opened is a table cb <i.2 4 The case chosen by the agenda B +---+ |0 4| |1 5| |2 6| |3 7| +---+ c 3j4 5 6j7 (Open) complex argument 3j_4 5 6j_7 Conjugate co 3j4 5 6j7 The case chosen by the agenda B 3j_4 5 6j_7
The complete definition of c can be seen by fixing it:
c f. -@|`+@.(-.@(-: +) ::(_1:))`(]`(|.&.>)`(|:&.>)@.(#@$@>))@.(-.@(-: >) ::0:)


Phone Numbers
One Item
Two Item
Three Item
Four Item
Dates
One Item
Two Item
Three Item
Four Item
Times
One Item
Two Item
Three Item
Four Item
Links
One Item
Two Item
Three Item
Four Item
Emails
One Item
Two Item
Three Item
Four Item
Emotion
Positive
Places
One Item


--- layout: post permalink: babybeddingtown.html Tags: Array NameOfCoupon: Baby Bedding Town Cash Back Summary: See our Baby Bedding Town Coupon Code, Baby Bedding Town Rebate, Baby Bedding Town Promo Code, Baby Bedding Town Discount, Baby Bedding Town Coupon Cash Back Rebate here. MetaKeywords: Baby Bedding Town Coupon Code, Baby Bedding Town Rebate, Baby Bedding Town Promo Code, Baby Bedding Town Cash Back Rebate, Baby Bedding Town Discount, Baby Bedding Town Coupon Image: images/30099.com/images/ LinkURL: http://www.shareasale.com/r.cfm?b=266790&u=412002&m=30099 affiliate_url_link: http://www.icouponblog.com/jane.php?id=7466 thesis_readmore: See the Baby Bedding Town Coupon thesis_thumb: http://www.icouponblog.com/tn.php?merchantURL=babybeddingtown.com Title: Save 5.00% - Baby Bedding Town Coupon Code for babybeddingtown.com. Baby Bedding Town Rebate & Discount thesis_description: Our Baby Bedding Town Discount Coupon Code for babybeddingtown.com. We have the best Baby Bedding Town Rebate anywhere. thesis_keywords: Baby Bedding Town, Baby Bedding Town Coupon Code, Baby Bedding Town Discount, Baby Bedding Town Rebate product_name: Baby Bedding Town hop_url: http://www.icouponblog.com/hop.php?id=7466 ---
Are you about to become grandparents for the first time? Or are you looking for the perfect bedding for your bundle of joy? Go no further than www.babybeddingtown.com. They have been in business since 1936 so they really have the expertise it takes to make bedding that is comfortable and good for the body and wallet. For high quality beddings, baby furniture, stroller, car seats, baby clothing, toys and lots more, visit www.babybeddingtown.com. It is the best place on web to buy high quality baby products at an affordable price. Check it out, use our discount coupons to save money.
If you are planning your baby’s nursery, you will find the finest furniture from designers like Kolcraft to Stanley Young America at an affordable price. Why settle for less when you can get so much more from www.babybeddingtown.com. For the finest and safest high chairs, mattresses, car seats and strollers and for beautiful, adorable outfits shop at www.babybeddingtown.com. You will love the prices and the designs and the comfort of all the products from www.babybeddingtown.com.
If you have a baby or wish to buy baby products check out www.babybeddingtown.com. It is the best place to buy products that are high quality, safe and secure and affordable. Whether you are setting up a nursery or buying for a baby shower, there is a huge selection of products to choose from. Use our discount coupons to save money.


SEND US A MESSAGE Contact form Submitted..!! We will be in touch Soon..!! Invalid Name.*This field is Required. *Invalid Phone Number.*This field is Required. *Invalid Email.*This field is Required. Message *This Message is too Short.*This field is Required. ClearSubmit


Advanced JavaScript - Scope
15 Jan 2017I have an obsession with learning, especially when it is something I want to master. I am currently reading You Don’t Know JS by Kyle Simpson. So far this book has really helped me solidify my understanding of what is really going on under the hood in the JavaScript engine. It’s been so helpful that I actually decided to put down the money for a monthly subscription to his Frontend Masters curriculum. Today I’m going to be covering the basics of scope in JS. If you would like to read more, I highly recommend checking out his book (it’s free on github!)
What is scope? I like to think of scope as a bubble. There can be objects, functions, and even other bubbles inside this bubble, but bubbles never overlap - meaning each bubble has its own “environment”. You can create a bubble by declaring a function, which in technical terms means authoring a function declaration. Contrast this with authoring a function expression, which is treated differently by the JavaScript compiler.
Since JavaScript treats its functions as first class citizens, any function that is declared will get precedence over other variables that are declared with the same name. It also means that if I decided to call foo() at the top of the file, it would behave as expected, unlike a call to bar, which I will explain below.
Contrary to popular belief, JavaScript is actually a compiled language.
var a = 2;
How does this code work? It may seem simple, and most people that are coming from different languages (including myself, I started out learning Ruby) will look at that code and think it is executed as a single statement. That is actually incorrect in JavaScript. When the compiler first encounters var a
it asks our current scope or bubble if variable a already exists - if it does, our compiler ignores the statement, if it doesn’t it creates a new variable in the current bubble. Remember that when a new variable is created initially its value is set to undefined. Once our compiler is done compiling code, our engine then handles the a = 2
assignment during run time. The engine comes across a = 2 and asks our current bubble, do you have a variable a? The bubble responds yes, hands the variable a off to engine and engine assigns it to the value 2.
What happens when our bubble doesn’t have the variable the engine is asking for? It looks for it outside of its current bubble (if its not in global, of course). The process repeats until it finally reaches the global scope and if it does not find the variable, the result is an error. However, there is a gotcha. If a variable is being assigned: for example there’s this following code:
during run time and it reaches global scope, global scope will create a new variable for us to use. As you can imagine, this will most likely lead to a whole bunch of nightmare situations. This is why a lot of developers advocate the use of “use strict”; on top of the source file to prevent this situation from ever happening.
I thought it seemed like a lot to take in at first, coming from a dynamic language like Ruby. There is also a whole set of details that I did not cover here that includes compiler terminology like “LHS” and “RHS” when our engine handles the code. But as I’m learning more and more about how JavaScript really works, the language is starting to grow on me. Even though I develop primarily in Angular, I’m confident that I have the necessary foundational skillset that will allow me pickup any future JS framework and hit the ground running.
If you like what you read you can check out my previous posts listed in my archive. Or you can check out the full source code for my latest project on github here.


| gdata.Crypto.PublicKey | index /usr/local/google/home/afshar/src/external-gdata-release/google3/src/gdata/Crypto/PublicKey/__init__.py |
Public-key encryption and signature algorithms.
Public-key encryption uses two different keys, one for encryption and
one for decryption. The encryption key can be made public, and the
decryption key is kept private. Many public-key algorithms can also
be used to sign messages, and some can *only* be used for signatures.
Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only)
Crypto.PublicKey.ElGamal (Signing and encryption)
Crypto.PublicKey.RSA (Signing, encryption, and blinding)
Crypto.PublicKey.qNEW (Signature only)
| Package Contents | ||||||
|
| Data | ||
| __all__ = ['RSA', 'DSA', 'ElGamal', 'qNEW'] __revision__ = '$Id: __init__.py,v 1.4 2003/04/03 20:27:13 akuchling Exp $' |


Party Tester
This application creates party records for testing the harvesting operation of the ARDC Party Infrastructure.
Party records are created under test sets. Each test set has a unique string that is used in the surname, person identifier and RIF-CS keys for the party records under them. This ensures that party records in each test set can be considered globally unique, which is required by some tests.
Test sets have a name and notes. These values do not appear in RIF-CS.
Party records have names, descriptions and a person identifier. That is all that is needed for testing.
Create a new test set and then create party records under it. Then harvest the party records from the OAI-PMH feed.
When re-running tests, create another test set so that the new test party records are independent from those previously created.


MADVISE
Section: Linux Programmer's Manual (2)
Updated: 2014-04-20
Index
Return to Main Contents
NAME
madvise - give advice about use of memory
SYNOPSIS
#include <sys/mman.h>
int madvise(void *addr, size_t length, int advice);
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
madvise():
_BSD_SOURCE
DESCRIPTION
The
madvise()
system call advises the kernel about how to handle paging input/output in
the address range beginning at address
addr
and with size
length
bytes.
It allows an application to tell the kernel how it expects to use
some mapped or shared memory areas, so that the kernel can choose
appropriate read-ahead and caching techniques.
This call does not influence the semantics of the application
(except in the case of
MADV_DONTNEED),
but
may influence its performance.
The kernel is free to ignore the advice.
The advice is indicated in the
advice
argument which can be
- MADV_NORMAL
-
No special treatment.
This is the default.
- MADV_RANDOM
-
Expect page references in random order.
(Hence, read ahead may be less useful than normally.)
- MADV_SEQUENTIAL
-
Expect page references in sequential order.
(Hence, pages in the given range can be aggressively read ahead,
and may be freed soon after they are accessed.)
- MADV_WILLNEED
-
Expect access in the near future.
(Hence, it might be a good idea to read some pages ahead.)
- MADV_DONTNEED
-
Do not expect access in the near future.
(For the time being, the application is finished with the given range,
so the kernel can free resources associated with it.)
Subsequent accesses of pages in this range will succeed, but will result
either in reloading of the memory contents from the underlying mapped file
(see
mmap(2))
or zero-fill-on-demand pages for mappings
without an underlying file.
- MADV_REMOVE (since Linux 2.6.16)
-
Free up a given range of pages
and its associated backing store.
Currently,
only shmfs/tmpfs supports this; other filesystems return with the
error
ENOSYS.
- MADV_DONTFORK (since Linux 2.6.16)
-
Do not make the pages in this range available to the child after a
fork(2).
This is useful to prevent copy-on-write semantics from changing
the physical location of a page(s) if the parent writes to it after a
fork(2).
(Such page relocations cause problems for hardware that
DMAs into the page(s).)
- MADV_DOFORK (since Linux 2.6.16)
-
Undo the effect of
MADV_DONTFORK,
restoring the default behavior, whereby a mapping is inherited across
fork(2).
- MADV_HWPOISON (since Linux 2.6.32)
-
Poison a page and handle it like a hardware memory corruption.
This operation is available only for privileged
(CAP_SYS_ADMIN)
processes.
This operation may result in the calling process receiving a
SIGBUS
and the page being unmapped.
This feature is intended for testing of memory error-handling code;
it is available only if the kernel was configured with
CONFIG_MEMORY_FAILURE.
- MADV_SOFT_OFFLINE (since Linux 2.6.33)
-
Soft offline the pages in the range specified by
addr
and
length.
The memory of each page in the specified range is preserved
(i.e., when next accessed, the same content will be visible,
but in a new physical page frame),
and the original page is offlined
(i.e., no longer used, and taken out of normal memory management).
The effect of the
MADV_SOFT_OFFLINE
operation is invisible to (i.e., does not change the semantics of)
the calling process.
This feature is intended for testing of memory error-handling code;
it is available only if the kernel was configured with
CONFIG_MEMORY_FAILURE.
- MADV_MERGEABLE (since Linux 2.6.32)
-
Enable Kernel Samepage Merging (KSM) for the pages in the range specified by
addr
and
length.
The kernel regularly scans those areas of user memory that have
been marked as mergeable,
looking for pages with identical content.
These are replaced by a single write-protected page (which is automatically
copied if a process later wants to update the content of the page).
KSM merges only private anonymous pages (see
mmap(2)).
The KSM feature is intended for applications that generate many
instances of the same data (e.g., virtualization systems such as KVM).
It can consume a lot of processing power; use with care.
See the Linux kernel source file
Documentation/vm/ksm.txt
for more details.
The
MADV_MERGEABLE
and
MADV_UNMERGEABLE
operations are available only if the kernel was configured with
CONFIG_KSM.
- MADV_UNMERGEABLE (since Linux 2.6.32)
-
Undo the effect of an earlier
MADV_MERGEABLE
operation on the specified address range;
KSM unmerges whatever pages it had merged in the address range specified by
addr
and
length.
- MADV_HUGEPAGE (since Linux 2.6.38)
-
Enables Transparent Huge Pages (THP) for pages in the range specified by
addr
and
length.
Currently, Transparent Huge Pages work only with private anonymous pages (see
mmap(2)).
The kernel will regularly scan the areas marked as huge page candidates
to replace them with huge pages.
The kernel will also allocate huge pages directly when the region is
naturally aligned to the huge page size (see
posix_memalign(2)).
This feature is primarily aimed at applications that use large mappings of
data and access large regions of that memory at a time (e.g., virtualization
systems such as QEMU).
It can very easily waste memory (e.g., a 2MB mapping that only ever accesses
1 byte will result in 2MB of wired memory instead of one 4KB page).
See the Linux kernel source file
Documentation/vm/transhuge.txt
for more details.
The
MADV_HUGEPAGE
and
MADV_NOHUGEPAGE
operations are available only if the kernel was configured with
CONFIG_TRANSPARENT_HUGEPAGE.
- MADV_NOHUGEPAGE (since Linux 2.6.38)
-
Ensures that memory in the address range specified by
addr
and
length
will not be collapsed into huge pages.
- MADV_DONTDUMP (since Linux 3.4)
-
Exclude from a core dump those pages in the range specified by
addr
and
length.
This is useful in applications that have large areas of memory
that are known not to be useful in a core dump.
The effect of
MADV_DONTDUMP
takes precedence over the bit mask that is set via the
/proc/PID/coredump_filter
file (see
core(5)).
- MADV_DODUMP (since Linux 3.4)
-
Undo the effect of an earlier
MADV_DONTDUMP.
RETURN VALUE
On success
madvise()
returns zero.
On error, it returns -1 and
errno
is set appropriately.
ERRORS
- EAGAIN
-
A kernel resource was temporarily unavailable.
- EBADF
-
The map exists, but the area maps something that isn't a file.
- EINVAL
-
This error can occur for the following reasons:
-
- *
-
The value
len
is negative.
- *
-
addr
is not page-aligned.
- *
-
advice
is not a valid value
- *
-
The application is attempting to release locked or shared pages (with
MADV_DONTNEED).
- *
-
MADV_MERGEABLE
or
MADV_UNMERGEABLE
was specified in
advice,
but the kernel was not configured with
CONFIG_KSM.
- EIO
-
(for
MADV_WILLNEED)
Paging in this area would exceed the process's
maximum resident set size.
- ENOMEM
-
(for
MADV_WILLNEED)
Not enough memory: paging in failed.
- ENOMEM
-
Addresses in the specified range are not currently
mapped, or are outside the address space of the process.
CONFORMING TO
POSIX.1b.
POSIX.1-2001 describes
posix_madvise(3)
with constants
POSIX_MADV_NORMAL,
POSIX_MADV_RANDOM,
and so on,
with a behavior close to that described here.
There is a similar
posix_fadvise(2)
for file access.
MADV_REMOVE,
MADV_DONTFORK,
MADV_DOFORK,
MADV_HWPOISON,
MADV_MERGEABLE,
and
MADV_UNMERGEABLE
are Linux-specific.
NOTES
Linux notes
The current Linux implementation (2.4.0) views this system call
more as a command than as advice and hence may return an error
when it cannot do what it usually would do in response to this
advice.
(See the ERRORS description above.)
This is nonstandard behavior.
The Linux implementation requires that the address
addr
be page-aligned, and allows
length
to be zero.
If there are some parts of the specified address range
that are not mapped, the Linux version of
madvise()
ignores them and applies the call to the rest (but returns
ENOMEM
from the system call, as it should).
SEE ALSO
getrlimit(2),
mincore(2),
mmap(2),
mprotect(2),
msync(2),
munmap(2),
prctl(2),
core(5)
Index
- NAME
-
- SYNOPSIS
-
- DESCRIPTION
-
- RETURN VALUE
-
- ERRORS
-
- CONFORMING TO
-
- NOTES
-
- Linux notes
-
- SEE ALSO
-
This document was created by
man2html,
using the manual pages.
Time: 02:54:49 GMT, September 18, 2014


| ID | Requirement Type |
Title |
Requirement |
Compliance |
R |
A |
I |
T |
Parent | Remark | Rationale | Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
REQ-1-1 UID |
Interface | REQ-1-1 Title | REQ-1-1 Statement | C | X | X | X | REQ-1-1 Rationale | ||||
| REQ-1-2 UID | REQ-1-2 Type | REQ-1-2 Title | REQ-1-2 Statement | C | X | X | X | REQ-1-2 Comment | REQ-1-2 Rationale |
| ID | Requirement Type |
Title |
Requirement |
Compliance |
R |
A |
I |
T |
Parent | Remark | Rationale | Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
REQ-2-1 UID |
Interface | REQ-2-1 Title | REQ-2-1 Statement | C | X | X | X | REQ-2-1 Rationale | ||||
| REQ-2-2 UID | REQ-2-2 Type | REQ-2-2 Title | REQ-2-2 Statement | C | X | X | X | REQ-2-2 Comment | REQ-2-2 Rationale |


STAR STATISTICS AND RESERVES APPS DEVELOPER INTERN
The Federal Reserve Bank of San Francisco believes in the diversity of our people, ideas, and experiences and our committed to building inclusive culture that representative of the communities we serve.
FEDERAL RESERVE SYSTEM OVERVIEW
The Federal Reserve Bank’s mission and work are built on over hundred years of strength, stability, and excellence. No other organization does what we do or has a greater impact on global economies. Our mission is to promote low inflation, full employment, and financial stability as well as provide services to financial institutions and the Treasury.
FEDERAL RESERVE BANK OF SAN FRANCISCO OVERVIEW
The Reserve Bank of San Francisco is one of Twelve Reserve Banks responsible for setting the nation’s monetary policy, serving the as the fiscal agent for the United States Treasury and supervising banking institutions, ensuring their stability and compliance with banking regulations. Our headquarters are in SF, CA serving the largest geographic district within the Federal Reserve System. With Branches offices in Los Angeles, Seattle, Portland, Salt Lake City, and Phoenix.
GOLD INTERN PROGRAM OVERVIEW
Invest in your future and consider joining the Growing Opportunity for Leadership and Diversity (GOLD) Program. Our paid internship program will offer you the opportunity to work on projects that supports the Bank’s business and impact the United States economy.
STATISTICS AND RESERVES APPLICATION DEPARTMENT OVERVIEW
The Statistics and Reserves application suite (STAR) collects information from Banks and other types of Depository Institutions. STAR analyzes and processes this collected data, providing valuable and critical information to the Federal Reserve Board of Governors, Federal Financial Institutions Examination Council (FFIEC), Federal Economists, the Treasury, and Congress. STAR also calculates Reserve Balance requirements, monitors maintained Reserve Balances, and delivers accounting statements to Banks and other Depository Institutions.
POSITION/PROJECT OVERVIEW
The candidate will work with STAR (Statistics And Reserve) team to perform research and help developing enterprise application including assisting automation testing.
This project will challenge the intern to work with people from different teams, understand the complicate business work flows. With the completion of this project, the intern can gain experience from different aspects of software development life cycle and developing automation testing script to ensure product quality.
KEY RESPONSIBILITIES
REQUIREMENTS:
U.S. Citizen or Permanent Residency
Graduating between 2020 and 2021 from a 4 year Bachelor degree program
Overall 3.0 GPA or better
Ability to work 40 hours week throughout the duration of the 10-12 week internship program.
PREFERRED SKILLS:
-
Angular
SQL
Java
Research
Writing/documentation
The Federal Reserve Bank of San Francisco is an Equal Opportunity Employer.


1. Command chains
Groovy lets you omit parentheses around the arguments of a
method call for top-level statements. "command chain" feature extends this by allowing us to chain such
parentheses-free method calls, requiring neither parentheses around arguments, nor dots between the chained calls.
The general idea is that a call like a b c d
will actually be equivalent to a(b).c(d)
. This
also works with multiple arguments, closure arguments, and even named arguments. Furthermore, such command chains can
also appear on the right-hand side of assignments. Let’s have a look at some examples
supported by this new syntax:
// equivalent to: turn(left).then(right)
turn left then right
// equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
take 2.pills of chloroquinine after 6.hours
// equivalent to: paint(wall).with(red, green).and(yellow)
paint wall with red, green and yellow
// with named parameters too
// equivalent to: check(that: margarita).tastes(good)
check that: margarita tastes good
// with closures as parameters
// equivalent to: given({}).when({}).then({})
given { } when { } then { }
It is also possible to use methods in the chain which take no arguments, but in that case, the parentheses are needed:
// equivalent to: select(all).unique().from(names)
select all unique() from names
If your command chain contains an odd number of elements, the chain will be composed of method / arguments, and will finish by a final property access:
// equivalent to: take(3).cookies
// and also this: take(3).getCookies()
take 3 cookies
This command chain approach opens up interesting possibilities in terms of the much wider range of DSLs which can now be written in Groovy.
The above examples illustrate using a command chain based DSL but not how to create one. There are various strategies that you can use, but to illustrate creating such a DSL, we will show a couple of examples - first using maps and Closures:
show = { println it }
square_root = { Math.sqrt(it) }
def please(action) {
[the: { what ->
[of: { n -> action(what(n)) }]
}]
}
// equivalent to: please(show).the(square_root).of(100)
please show the square_root of 100
// ==> 10.0
As a second example, consider how you might write a DSL for simplifying
one of your existing APIs. Maybe you need to put this code in front of
customers, business analysts or testers who might be not hard-core Java
developers. We’ll use the Splitter
from the Google
Guava libraries project as it
already has a nice Fluent API. Here is how we might use it out of the
box:
@Grab('com.google.guava:guava:r09')
import com.google.common.base.*
def result = Splitter.on(',').trimResults(CharMatcher.is('_' as char)).split("_a ,_b_ ,c__").iterator().toList()
It reads fairly well for a Java developer but if that is not your target audience or you have many such statements to write, it could be considered a little verbose. Again, there are many options for writing a DSL. We’ll keep it simple with Maps and Closures. We’ll first write a helper method:
@Grab('com.google.guava:guava:r09')
import com.google.common.base.*
def split(string) {
[on: { sep ->
[trimming: { trimChar ->
Splitter.on(sep).trimResults(CharMatcher.is(trimChar as char)).split(string).iterator().toList()
}]
}]
}
now instead of this line from our original example:
def result = Splitter.on(',').trimResults(CharMatcher.is('_' as char)).split("_a ,_b_ ,c__").iterator().toList()
we can write this:
def result = split "_a ,_b_ ,c__" on ',' trimming '_\'
2. Operator overloading
Various operators in Groovy are mapped onto regular method calls on objects.
This allows you to provide your own Java or Groovy objects which can take advantage of operator overloading. The following table describes the operators supported in Groovy and the methods they map to.
| Operator | Method |
|---|---|
|
a.plus(b) |
|
a.minus(b) |
|
a.multiply(b) |
|
a.power(b) |
|
a.div(b) |
|
a.mod(b) |
|
a.or(b) |
|
a.and(b) |
|
a.xor(b) |
|
a.next() |
|
a.previous() |
|
a.getAt(b) |
|
a.putAt(b, c) |
|
a.leftShift(b) |
|
a.rightShift(b) |
|
a.rightShiftUnsigned(b) |
|
b.isCase(a) |
|
a.asBoolean() |
|
a.bitwiseNegate() |
|
a.negative() |
|
a.positive() |
|
a.asType(b) |
|
a.equals(b) |
|
! a.equals(b) |
|
a.compareTo(b) |
|
a.compareTo(b) > 0 |
|
a.compareTo(b) >= 0 |
|
a.compareTo(b) < 0 |
|
a.compareTo(b) <= 0 |
3. Script base classes
3.1. The Script class
Groovy scripts are always compiled to classes. For example, a script as simple as:
println 'Hello from Groovy'
is compiled to a class extending the abstract groovy.lang.Script class. This class contains a single abstract
method called run. When a script is compiled, then its body will become the run method, while the other methods
found in the script are found in the implementing class. The Script
class provides base support for integration
with your application through the Binding
object, as illustrated in this example:
def binding = new Binding() (1)
def shell = new GroovyShell(binding) (2)
binding.setVariable('x',1) (3)
binding.setVariable('y',3)
shell.evaluate 'z=2*x+y' (4)
assert binding.getVariable('z') == 5 (5)
| 1 | a binding is used to share data between the script and the calling class |
| 2 | a GroovyShell can be used with this binding |
| 3 | input variables are set from the calling class inside the binding |
| 4 | then the script is evaluated |
| 5 | and the z variable has been "exported" into the binding |
This is a very practical way to share data between the caller and the script, however it may be insufficient or not practical in some cases. For that purpose, Groovy allows you to set your own base script class. A base script class has to extend groovy.lang.Script and be a single abstract method type:
abstract class MyBaseClass extends Script {
String name
public void greet() { println "Hello, $name!" }
}
Then the custom script base class can be declared in the compiler configuration, for example:
def config = new CompilerConfiguration() (1)
config.scriptBaseClass = 'MyBaseClass' (2)
def shell = new GroovyShell(this.class.classLoader, config) (3)
shell.evaluate """
setName 'Judith' (4)
greet()
"""
| 1 | create a custom compiler configuration |
| 2 | set the base script class to our custom base script class |
| 3 | then create a GroovyShell using that configuration |
| 4 | the script will then extend the base script class, giving direct access to the name property and greet method |
3.2. The @BaseScript annotation
As an alternative, it is also possible to use the @BaseScript
annotation directly into a script:
import groovy.transform.BaseScript
@BaseScript MyBaseClass baseScript
setName 'Judith'
greet()
where @BaseScript
should annotate a variable which type is the class of the base script. Alternatively, you can set
the base script class as a member of the @BaseScript
annotation itself:
@BaseScript(MyBaseClass)
import groovy.transform.BaseScript
setName 'Judith'
greet()
3.3. Alternate abstract method
We have seen that the base script class is a single abstract method type that needs to implement the run
method. The
run
method is executed by the script engine automatically. In some circumstances it may be interesting to have a base
class which implements the run
method, but provides an alternative abstract method to be used for the script body.
For example, the base script run
method might perform some initialization before the run
method is executed. This
is possible by doing this:
abstract class MyBaseClass extends Script {
int count
abstract void scriptBody() (1)
def run() {
count++ (2)
scriptBody() (3)
count (4)
}
}
| 1 | the base script class should define one (and only one) abstract method |
| 2 | the run method can be overriden and perform a task before executing the script body |
| 3 | run calls the abstract scriptBody method which will delegate to the user script |
| 4 | then it can return something else than the value from the script |
If you execute this code:
def result = shell.evaluate """
println 'Ok'
"""
assert result == 1
Then you will see that the script is executed, but the result of the evaluation is 1
as returned by the run
method of the base class. It is even clearer if you use parse
instead of evaluate
, because it would allow you to
execute the run
method several times on the same script instance:
def script = shell.parse("println 'Ok'")
assert script.run() == 1
assert script.run() == 2
4. Adding properties to numbers
In Groovy number types are considered equal to any other types. As such, it is possible to enhance numbers by adding properties or methods to them. This can be very handy when dealing with measurable quantities for example. Details about how existing classes can be enhanced in Groovy are found in the extension modules section or the categories section.
An illustration of this can be found in Groovy using the TimeCategory
:
use(TimeCategory) {
println 1.minute.from.now (1)
println 10.hours.ago
def someDate = new Date() (2)
println someDate - 3.months
}
| 1 | using the TimeCategory , a property minute is added to the Integer class |
| 2 | similarily, the months method returns a groovy.time.DatumDependentDuration which can be used in calculus |
Categories are lexically bound, making them a great fit for internal DSLs.
5. @DelegatesTo
5.1. Explaining delegation strategy at compile time
@groovy.lang.DelegatesTo
is a documentation and compile-time annotation aimed at:
-
documenting APIs that use closures as arguments
-
providing type information for the static type checker and compiler
The Groovy language is a platform of choice for building DSLs. Using closures, it’s quite easy to create custom control structures, as well as it is simple to create builders. Imagine that you have the following code:
email {
from<EMAIL_ADDRESS>to<EMAIL_ADDRESS>subject 'The pope has resigned!'
body {
p 'Really, the pope has resigned!'
}
}
One way of implementing this is using the builder strategy, which
implies a method, named email
which accepts a closure as an argument.
The method may delegate subsequent calls to an object that implements
the from
, to
, subject
and body
methods. Again, body
is a
method which accepts a closure as an argument and that uses the builder
strategy.
Implementing such a builder is usually done the following way:
def email(Closure cl) {
def email = new EmailSpec()
def code = cl.rehydrate(email, this, this)
code.resolveStrategy = Closure.DELEGATE_ONLY
code()
}
the EmailSpec
class implements the from
, to
, … methods. By
calling rehydrate
, we’re creating a copy of the closure for which we
set the delegate
, owner
and thisObject
values. Setting the owner
and the this
object is not very important here since we will use the
DELEGATE_ONLY
strategy which says that the method calls will be
resolved only against the delegate of the closure.
class EmailSpec {
void from(String from) { println "From: $from"}
void to(String... to) { println "To: $to"}
void subject(String subject) { println "Subject: $subject"}
void body(Closure body) {
def bodySpec = new BodySpec()
def code = body.rehydrate(bodySpec, this, this)
code.resolveStrategy = Closure.DELEGATE_ONLY
code()
}
}
The EmailSpec
class has itself a body
method accepting a closure that is cloned and executed. This is what
we call the builder pattern in Groovy.
One of the problems with the code that we’ve shown is that the user of
the email
method doesn’t have any information about the methods that
he’s allowed to call inside the closure. The only possible information
is from the method documentation. There are two issues with this: first
of all, documentation is not always written, and if it is, it’s not
always available (javadoc not downloaded, for example). Second, it
doesn’t help IDEs. What would be really interesting, here, is for IDEs
to help the developer by suggesting, once they are in the closure body,
methods that exist on the email
class.
Moreover, if the user calls a method in the closure which is not defined
by the EmailSpec
class, the IDE should at least issue a warning (because
it’s very likely that it will break at runtime).
One more problem with the code above is that it is not compatible with static type checking. Type checking would let the user know if a method call is authorized at compile time instead of runtime, but if you try to perform type checking on this code:
email {
from<EMAIL_ADDRESS>to<EMAIL_ADDRESS>subject 'The pope has resigned!'
body {
p 'Really, the pope has resigned!'
}
}
Then the type checker will know that there’s an email
method accepting
a Closure
, but it will complain for every method call inside the
closure, because from
, for example, is not a method which is defined
in the class. Indeed, it’s defined in the EmailSpec
class and it has
absolutely no hint to help it knowing that the closure delegate will, at
runtime, be of type EmailSpec
:
@groovy.transform.TypeChecked
void sendEmail() {
email {
from<EMAIL_ADDRESS>to<EMAIL_ADDRESS>subject 'The pope has resigned!'
body {
p 'Really, the pope has resigned!'
}
}
}
will fail compilation with errors like this one:
[Static type checking] - Cannot find matching method MyScript#from(java.lang.String). Please check if the declared type is right and if the method exists. @ line 31, column 21. from<EMAIL_ADDRESS>5.2. @DelegatesTo
For those reasons, Groovy 2.1 introduced a new annotation
named @DelegatesTo
. The goal of this annotation is to solve both the
documentation issue, that will let your IDE know about the expected
methods in the closure body, and it will also solve the type checking
issue, by giving hints to the compiler about what are the potential
receivers of method calls in the closure body.
The idea is to annotate the Closure
parameter of the email
method:
def email(@DelegatesTo(EmailSpec) Closure cl) {
def email = new EmailSpec()
def code = cl.rehydrate(email, this, this)
code.resolveStrategy = Closure.DELEGATE_ONLY
code()
}
What we’ve done here is telling the compiler (or the IDE) that when the
method will be called with a closure, the delegate of this closure will
be set to an object of type email
. But there is still a problem: the
default delegation strategy is not the one which is used in our method.
So we will give more information and tell the compiler (or the IDE) that
the delegation strategy is also changed:
def email(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=EmailSpec) Closure cl) {
def email = new EmailSpec()
def code = cl.rehydrate(email, this, this)
code.resolveStrategy = Closure.DELEGATE_ONLY
code()
}
Now, both the IDE and the type checker (if you are using @TypeChecked
)
will be aware of the delegate and the delegation strategy. This is very
nice because it will both allow the IDE to provide smart completion, but
it will also remove errors at compile time that exist only because the
behaviour of the program is normally only known at runtime!
The following code will now pass compilation:
@TypeChecked
void doEmail() {
email {
from<EMAIL_ADDRESS>to<EMAIL_ADDRESS>subject 'The pope has resigned!'
body {
p 'Really, the pope has resigned!'
}
}
}
5.3. DelegatesTo modes
@DelegatesTo
supports multiple modes that we will describe with examples
in this section.
5.3.1. Simple delegation
In this mode, the only mandatory parameter is the value which says to
which class we delegate calls. Nothing more. We’re telling the compiler
that the type of the delegate will always be of the type documented
by @DelegatesTo
(note that it can be a subclass, but if it is, the
methods defined by the subclass will not be visible to the type
checker).
void body(@DelegatesTo(BodySpec) Closure cl) {
// ...
}
5.3.2. Delegation strategy
In this mode, you must specify both the delegate class and a
delegation strategy. This must be used if the closure will not be called
with the default delegation strategy, which is Closure.OWNER_FIRST
.
void body(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=BodySpec) Closure cl) {
// ...
}
5.3.3. Delegate to parameter
In this variant, we will tell the compiler that we are delegating to another parameter of the method. Take the following code:
def exec(Object target, Closure code) {
def clone = code.rehydrate(target, this, this)
clone()
}
Here, the delegate which will be used is not created inside the exec
method. In fact, we take an argument of the method and delegate to it.
Usage may look like this:
def email = new Email()
exec(email) {
from '...'
to '...'
send()
}
Each of the method calls are delegated to the email
parameter. This is
a widely used pattern which is also supported by @DelegatesTo
using a
companion annotation:
def<EMAIL_ADDRESS>Object target, @DelegatesTo Closure code) {
def clone = code.rehydrate(target, this, this)
clone()
}
A closure is annotated with @DelegatesTo
, but this time, without
specifying any class. Instead, we’re annotating another parameter
with @DelegatesTo.Target
. The type of the delegate is then determined
at compile time. One could think that we are using the parameter type,
which in this case is Object
but this is not true. Take this code:
class Greeter {
void sayHello() { println 'Hello' }
}
def greeter = new Greeter()
exec(greeter) {
sayHello()
}
Remember that this works out of the box without having to annotate
with @DelegatesTo
. However, to make the IDE aware of the delegate
type, or the type checker aware of it, we need to add @DelegatesTo
.
And in this case, it will now that the Greeter
variable is of
type Greeter
, so it will not report errors on the sayHello
method even if the exec method doesn’t explicitly define the target as
of type Greeter. This is a very powerful feature, because it prevents
you from writing multiple versions of the same exec
method for
different receiver types!
In this mode, the @DelegatesTo
annotation also supports the strategy
parameter that we’ve described upper.
5.3.4. Multiple closures
In the previous example, the exec
method accepted only one closure,
but you may have methods that take multiple closures:
void fooBarBaz(Closure foo, Closure bar, Closure baz) {
...
}
Then nothing prevents you from annotating each closure
with @DelegatesTo
:
class Foo { void foo(String msg) { println "Foo ${msg}!" } }
class Bar { void bar(int x) { println "Bar ${x}!" } }
class Baz { void baz(Date d) { println "Baz ${d}!" } }
void fooBarBaz(@DelegatesTo(Foo) Closure foo, @DelegatesTo(Bar) Closure bar, @DelegatesTo(Baz) Closure baz) {
...
}
But more importantly, if you have multiple closures and multiple arguments, you can use several targets:
void fooBarBaz(
@DelegatesTo.Target('foo') foo,
@DelegatesTo.Target('bar') bar,
@DelegatesTo.Target('baz') baz,
@DelegatesTo(target='foo') Closure cl1,
@DelegatesTo(target='bar') Closure cl2,
@DelegatesTo(target='baz') Closure cl3) {
cl1.rehydrate(foo, this, this).call()
cl2.rehydrate(bar, this, this).call()
cl3.rehydrate(baz, this, this).call()
}
def a = new Foo()
def b = new Bar()
def c = new Baz()
fooBarBaz(
a, b, c,
{ foo('Hello') },
{ bar(123) },
{ baz(new Date()) }
)
| At this point, you may wonder why we don’t use the parameter names as references. The reason is that the information (the parameter name) is not always available (it’s a debug-only information), so it’s a limitation of the JVM. |
5.3.5. Delegating to a generic type
In some situations, it is interesting to instruct the IDE or the compiler that the delegate type will not be a parameter but a generic type. Imagine a configurator that runs on a list of elements:
public <T> void configure(List<T> elements, Closure configuration) {
elements.each { e->
def clone = configuration.rehydrate(e, this, this)
clone.resolveStrategy = Closure.DELEGATE_FIRST
clone.call()
}
}
Then this method can be called with any list like this:
@groovy.transform.ToString
class Realm {
String name
}
List<Realm> list = []
3.times { list << new Realm() }
configure(list) {
name = 'My Realm'
}
assert list.every { it.name == 'My Realm' }
To let the type checker and the IDE know that the configure
method calls the closure on each element of the list, you
need to use @DelegatesTo
differently:
public <T> void configure(
@DelegatesTo.Target List<T> elements,
@DelegatesTo(strategy=Closure.DELEGATE_FIRST, genericTypeIndex=0) Closure configuration) {
def clone = configuration.rehydrate(e, this, this)
clone.resolveStrategy = Closure.DELEGATE_FIRST
clone.call()
}
@DelegatesTo
takes an optional genericTypeIndex
argument that tells what is the index of the generic type that will
be used as the delegate type. This must be used in conjunction with @DelegatesTo.Target
and the index starts at 0. In
the example above, that means that the delegate type is resolved against List<T>
, and since the generic type at index
0 is T
and inferred as a Realm
, the type checker infers that the delegate type will be of type Realm
.
We’re using a genericTypeIndex instead of a placeholder (T ) because of JVM limitations.
|
5.3.6. Delegating to an arbitrary type
It is possible that none of the options above can represent the type you want to delegate to. For example, let’s define a mapper class which is parametrized with an object and defines a map method which returns an object of another type:
class Mapper<T,U> { (1)
final T value (2)
Mapper(T value) { this.value = value }
U map(Closure<U> producer) { (3)
producer.delegate = value
producer()
}
}
| 1 | The mapper class takes two generic type arguments: the source type and the target type |
| 2 | The source object is stored in a final field |
| 3 | The map method asks to convert the source object to a target object |
As you can see, the method signature from map
does not give any information about what object will
be manipulated by the closure. Reading the method body, we know that it will be the value
which is
of type T
, but T
is not found in the method signature, so we are facing a case where none of the
available options for @DelegatesTo
is suitable. For example, if we try to statically compile this code:
def mapper = new Mapper<String,Integer>('Hello')
assert mapper.map { length() } == 5
Then the compiler will fail with:
Static type checking] - Cannot find matching method TestScript0#length()
In that case, you can use the type
member of the @DelegatesTo
annotation to reference T
as a type token:
class Mapper<T,U> {
final T value
Mapper(T value) { this.value = value }
U map(@DelegatesTo(type="T") Closure<U> producer) { (1)
producer.delegate = value
producer()
}
}
| 1 | The @DelegatesTo annotation references a generic type which is not found in the method signature |
Note that you are not limited to generic type tokens. The type
member can be used to represent complex types, such
as List<T>
or Map<T,List<U>>
. The reason why you should use that in last resort is that the type is only checked
when the type checker finds usage of @DelegatesTo
, not when the annotated method itself is compiled. This means that
type safety is only ensured at the call site. Additionally, compilation will be slower (though probably unnoticeable for
most cases).
6. Compilation customizers
6.1. Introduction
Whether you are using groovyc
to compile classes or a GroovyShell
,
for example, to execute scripts, under the hood, a compiler configuration is used. This configuration holds information
like the source encoding or the classpath but it can also be used to perform more operations like adding imports by
default, applying AST transformations transparently or disabling global AST transformations.
The goal of compilation customizers is to make those common tasks easy to implement. For that, the CompilerConfiguration
class is the entry point. The general schema will always be based on the following code:
import org.codehaus.groovy.control.CompilerConfiguration
// create a configuration
def config = new CompilerConfiguration()
// tweak the configuration
config.addCompilationCustomizers(...)
// run your script
def shell = new GroovyShell(config)
shell.evaluate(script)
Compilation customizers must extend the org.codehaus.groovy.control.customizers.CompilationCustomizer class. A customizer works:
-
on a specific compilation phase
-
on every class node being compiled
You can implement your own compilation customizer but Groovy includes some of the most common operations.
6.2. Import customizer
Using this compilation customizer, your code will have imports added transparently. This is in particular useful for scripts implementing a DSL where you want to avoid users from having to write imports. The import customizer will let you add all the variants of imports the Groovy language allows, that is:
-
class imports, optionally aliased
-
star imports
-
static imports, optionally aliased
-
static star imports
import org.codehaus.groovy.control.customizers.ImportCustomizer
def icz = new ImportCustomizer()
// "normal" import
icz.addImports('java.util.concurrent.atomic.AtomicInteger', 'java.util.concurrent.ConcurrentHashMap')
// "aliases" import
icz.addImport('CHM', 'java.util.concurrent.ConcurrentHashMap')
// "static" import
icz.addStaticImport('java.lang.Math', 'PI') // import static java.lang.Math.PI
// "aliased static" import
icz.addStaticImport('pi', 'java.lang.Math', 'PI') // import static java.lang.Math.PI as pi
// "star" import
icz.addStarImports 'java.util.concurrent' // import java.util.concurrent.*
// "static star" import
icz.addStaticStars 'java.lang.Math' // import static java.lang.Math.*
A detailed description of all shortcuts can be found in org.codehaus.groovy.control.customizers.ImportCustomizer
6.3. AST transformation customizer
The AST transformation customizer is meant to apply AST transformations transparently. Unlike global AST transformations that apply on every class beeing compiled as long as the transform is found on classpath (which has drawbacks like increasing the compilation time or side effects due to transformations applied where they should not), the customizer will allow you to selectively apply a transform only for specific scripts or classes.
As an example, let’s say you want to be able to use @Log
in a script.
The problem is that @Log
is normally applied on a class node and a
script, by definition, doesn’t require one. But implementation wise,
scripts are classes, it’s just that you cannot annotate this implicit
class node with @Log
. Using the AST customizer, you have a workaround
to do it:
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
import groovy.util.logging.Log
def acz = new ASTTransformationCustomizer(Log)
config.addCompilationCustomizers(acz)
That’s all! Internally, the @Log
AST transformation is applied to
every class node in the compilation unit. This means that it will be
applied to the script, but also to classes defined within the script.
If the AST transformation that you are using accepts parameters, you can use parameters in the constructor too:
def acz = new ASTTransformationCustomizer(Log, value: 'LOGGER')
// use name 'LOGGER' instead of the default 'log'
config.addCompilationCustomizers(acz)
As the AST transformation customizers works with objects instead of AST
nodes, not all values can be converted to AST transformation parameters.
For example, primitive types are converted to ConstantExpression
(that
is LOGGER
is converted to new ConstantExpression('LOGGER')
, but if
your AST transformation takes a closure as an argument, then you have to
give it a ClosureExpression
, like in the following example:
def configuration = new CompilerConfiguration()
def expression = new AstBuilder().buildFromCode(CompilePhase.CONVERSION) { -> true }.expression[0]
def customizer = new ASTTransformationCustomizer(ConditionalInterrupt, value: expression, thrown: SecurityException)
configuration.addCompilationCustomizers(customizer)
def shell = new GroovyShell(configuration)
shouldFail(SecurityException) {
shell.evaluate("""
// equivalent to adding @ConditionalInterrupt(value={true}, thrown: SecurityException)
class MyClass {
void doIt() { }
}
new MyClass().doIt()
""")
}
For a complete list of options, please refer to org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
6.4. Secure AST customizer
This customizer will allow the developer of a DSL to restrict the grammar of the language, to prevent users from using some constructs, for example. It is only ``secure'' in that sense only and it is very important to understand that it does not replace a security manager. The only reason for it to exist is to limit the expressiveness of the language. This customizer only works at the AST (abstract syntax tree) level, not at runtime! It can be strange at first glance, but it makes much more sense if you think of Groovy as a platform to build DSLs. You may not want a user to have a complete language at hand. In the example below, we will demonstrate it using an example of language that only allows arithmetic operations, but this customizer allows you to:
-
allow/disallow creation of closures
-
allow/disallow imports
-
allow/disallow package definition
-
allow/disallow definition of methods
-
restrict the receivers of method calls
-
restrict the kind of AST expressions a user can use
-
restrict the tokens (grammar-wise) a user can use
-
restrict the types of the constants that can be used in code
For all those features, the secure AST customizer works using either a whitelist (list of elements that are allowed) or a blacklist (list of elements that are disallowed). For each type of feature (imports, tokens, …) you have the choice to use either a whitelist or a blacklist, but you can mix whitelists and blacklists for distinct features. In general, you will choose whitelists (disallow all, allow selected).
import org.codehaus.groovy.control.customizers.SecureASTCustomizer
import static org.codehaus.groovy.syntax.Types.* (1)
def scz = new SecureASTCustomizer()
scz.with {
closuresAllowed = false // user will not be able to write closures
methodDefinitionAllowed = false // user will not be able to define methods
importsWhitelist = [] // empty whitelist means imports are disallowed
staticImportsWhitelist = [] // same for static imports
staticStarImportsWhitelist = ['java.lang.Math'] // only java.lang.Math is allowed
// the list of tokens the user can find
// constants are defined in org.codehaus.groovy.syntax.Types
tokensWhitelist = [ (1)
PLUS,
MINUS,
MULTIPLY,
DIVIDE,
MOD,
POWER,
PLUS_PLUS,
MINUS_MINUS,
COMPARE_EQUAL,
COMPARE_NOT_EQUAL,
COMPARE_LESS_THAN,
COMPARE_LESS_THAN_EQUAL,
COMPARE_GREATER_THAN,
COMPARE_GREATER_THAN_EQUAL,
].asImmutable()
// limit the types of constants that a user can define to number types only
constantTypesClassesWhiteList = [ (2)
Integer,
Float,
Long,
Double,
BigDecimal,
Integer.TYPE,
Long.TYPE,
Float.TYPE,
Double.TYPE
].asImmutable()
// method calls are only allowed if the receiver is of one of those types
// be careful, it's not a runtime type!
receiversClassesWhiteList = [ (2)
Math,
Integer,
Float,
Double,
Long,
BigDecimal
].asImmutable()
}
| 1 | use for token types from org.codehaus.groovy.syntax.Types |
| 2 | you can use class literals here |
If what the secure AST customizer provides out of the box isn’t enough
for your needs, before creating your own compilation customizer, you
might be interested in the expression and statement checkers that the
AST customizer supports. Basically, it allows you to add custom checks
on the AST tree, on expressions (expression checkers) or statements
(statement checkers). For this, you must
implement org.codehaus.groovy.control.customizers.SecureASTCustomizer.StatementChecker
or org.codehaus.groovy.control.customizers.SecureASTCustomizer.ExpressionChecker
.
Those interfaces define a single method called isAuthorized
, returning
a boolean, and taking a Statement
(or Expression
) as a parameter. It
allows you to perform complex logic over expressions or statements to
tell if a user is allowed to do it or not.
For example, there’s no predefined configuration flag in the customizer which will let you prevent people from using an attribute expression. Using a custom checker, it is trivial:
def scz = new SecureASTCustomizer()
def checker = { expr ->
!(expr instanceof AttributeExpression)
} as SecureASTCustomizer.ExpressionChecker
scz.addExpressionCheckers(checker)
Then we can make sure that this works by evaluating a simple script:
new GroovyShell(config).evaluate '''
class A {
int val
}
def a = new A(val: 123)
a.@val (1)
'''
| 1 | will fail compilation |
Statements can be checked using org.codehaus.groovy.control.customizers.SecureASTCustomizer.StatementChecker Expressions can be checked using org.codehaus.groovy.control.customizers.SecureASTCustomizer.ExpressionChecker
6.5. Source aware customizer
This customizer may be used as a filter on other customizers. The
filter, in that case, is the org.codehaus.groovy.control.SourceUnit
.
For this, the source aware customizer takes another customizer as a
delegate, and it will apply customization of that delegate only and only
if predicates on the source unit match.
SourceUnit
gives you access to multiple things but in particular the
file being compiled (if compiling from a file, of course). It gives
you the potential to perform operation based on the file name, for
example. Here is how you would create a source aware customizer:
import org.codehaus.groovy.control.customizers.SourceAwareCustomizer
import org.codehaus.groovy.control.customizers.ImportCustomizer
def delegate = new ImportCustomizer()
def sac = new SourceAwareCustomizer(delegate)
Then you can use predicates on the source aware customizer:
// the customizer will only be applied to classes contained in a file name ending with 'Bean'
sac.baseNameValidator = { baseName ->
baseName.endsWith 'Bean'
}
// the customizer will only be applied to files which extension is '.spec'
sac.extensionValidator = { ext -> ext == 'spec' }
// source unit validation
// allow compilation only if the file contains at most 1 class
sac.sourceUnitValidator = { SourceUnit sourceUnit -> sourceUnit.AST.classes.size() == 1 }
// class validation
// the customizer will only be applied to classes ending with 'Bean'
sac.classValidator = { ClassNode cn -> cn.endsWith('Bean') }
6.6. Customizer builder
If you are using compilation customizers in Groovy code (like the
examples above) then you can use an alternative syntax to customize compilation.
A builder (org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder
)
simplifies the creation of customizers using a hierarchical DSL.
import org.codehaus.groovy.control.CompilerConfiguration
import static org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder.withConfig (1)
def conf = new CompilerConfiguration()
withConfig(conf) {
// ... (2)
}
| 1 | static import of the builder method |
| 2 | configuration goes here |
The code sample above shows how to use the builder. A static method, withConfig, takes a closure corresponding to the builder code, and automatically registers compilation customizers to the configuration. Every compilation customizer available in the distribution can be configured this way:
6.6.1. Import customizer
withConfig(configuration) {
imports { // imports customizer
normal 'my.package.MyClass' // a normal import
alias 'AI', 'java.util.concurrent.atomic.AtomicInteger' // an aliased import
star 'java.util.concurrent' // star imports
staticMember 'java.lang.Math', 'PI' // static import
staticMember 'pi', 'java.lang.Math', 'PI' // aliased static import
}
}
6.6.2. AST transformation customizer
withConfig(conf) {
ast(Log) (1)
}
withConfig(conf) {
ast(Log, value: 'LOGGER') (2)
}
| 1 | apply @Log transparently |
| 2 | apply @Log with a different name for the logger |
6.6.3. Secure AST customizer
withConfig(conf) {
secureAst {
closuresAllowed = false
methodDefinitionAllowed = false
}
}
6.6.4. Source aware customizer
withConfig(configuration){
source(extension: 'sgroovy') {
ast(CompileStatic) (1)
}
}
withConfig(configuration){
source(extensions: ['sgroovy','sg']) {
ast(CompileStatic) (2)
}
}
withConfig(configuration) {
source(extensionValidator: { it.name in ['sgroovy','sg']}) {
ast(CompileStatic) (2)
}
}
withConfig(configuration) {
source(basename: 'foo') {
ast(CompileStatic) (3)
}
}
withConfig(configuration) {
source(basenames: ['foo', 'bar']) {
ast(CompileStatic) (4)
}
}
withConfig(configuration) {
source(basenameValidator: { it in ['foo', 'bar'] }) {
ast(CompileStatic) (4)
}
}
withConfig(configuration) {
source(unitValidator: { unit -> !unit.AST.classes.any { it.name == 'Baz' } }) {
ast(CompileStatic) (5)
}
}
| 1 | apply CompileStatic AST annotation on .sgroovy files |
| 2 | apply CompileStatic AST annotation on .sgroovy or .sg files |
| 3 | apply CompileStatic AST annotation on files whose name is 'foo' |
| 4 | apply CompileStatic AST annotation on files whose name is 'foo' or 'bar' |
| 5 | apply CompileStatic AST annotation on files that do not contain a class named 'Baz' |
6.6.5. Inlining a customizer
Inlined customizer allows you to write a compilation customizer directly, without having to create a class for it.
withConfig(configuration) {
inline(phase:'CONVERSION') { source, context, classNode -> (1)
println "visiting $classNode" (2)
}
}
| 1 | define an inlined customizer which will execute at the CONVERSION phase |
| 2 | prints the name of the class node being compiled |
6.7. Config script flag
So far, we have described how you can customize compilation using
a CompilationConfiguration
class, but this is only possible if you
embed Groovy and that you create your own instances
of CompilerConfiguration
(then use it to create a
GroovyShell
, GroovyScriptEngine
, …).
If you want it to be applied on the classes you compile with the normal
Groovy compiler (that is to say with groovyc
, ant
or gradle
,
for example), it is possible to use a compilation flag named configscript
that takes a Groovy configuration script as argument.
This script gives you access to the CompilerConfiguration
instance before
the files are compiled (exposed into the configuration script as a variable named configuration
),
so that you can tweak it.
It also transparently integrates the compiler configuration builder above. As an example, let’s see how you would activate static compilation by default on all classes.
6.7.1. Static compilation by default
Normally, classes in Groovy are compiled with a dynamic runtime. You can activate static compilation
by placing an annotation named @CompileStatic
on any class. Some people would like to have this
mode activated by default, that is to say not having to annotated classes. Using configscript
,
this is possible. First of all, you need to create a file named config.groovy
into src/conf
with
the following contents:
withConfig(configuration) { (1)
ast(groovy.transform.CompileStatic)
}
| 1 | configuration references a CompilerConfiguration instance |
That is actually all you need. You don’t have to import the builder, it’s automatically exposed in the script. Then, compile your files using the following command line:
groovyc -configscript src/conf/config.groovy src/main/groovy/MyClass.groovy
We strongly recommend you to separate configuration files from classes,
hence why we suggest using the src/main
and src/conf
directories above.
6.8. AST transformations
If:
-
runtime metaprogramming doesn’t allow you do do what you want
-
you need to improve the performance of the execution of your DSLs
-
you want to leverage the same syntax as Groovy but with different semantics
-
you want to improve support for type checking in your DSLs
Then AST transformations are the way to go. Unlike the techniques used so far, AST transformations are meant to change or generate code before it is compiled to bytecode. AST transformations are capable of adding new methods at compile time for example, or totally changing the body of a method based on your needs. They are a very powerful tool but also come at the price of not being easy to write. For more information about AST transformations, please take a look at the compile-time metaprogramming section of this manual.
7. Custom type checking extensions
It may be interesting, in some circumstances, to provide feedback about wrong code to the user as soon as possible, that is to say when the DSL script is compiled, rather than having to wait for the execution of the script. However, this is not often possible with dynamic code. Groovy actually provides a practical answer to this known as type checking extensions.
8. Builders
(TBD)
8.2. Existing builders
(TBD)
8.2.3. SaxBuilder
A builder for generating Simple API for XML (SAX) events.
If you have the following SAX handler:
class LogHandler extends org.xml.sax.helpers.DefaultHandler {
String log = ''
void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes) {
log += "Start Element: $localName, "
}
void endElement(String uri, String localName, String qName) {
log += "End Element: $localName, "
}
}
You can use SaxBuilder
to generate SAX events for the handler like this:
def handler = new LogHandler()
def builder = new groovy.xml.SAXBuilder(handler)
builder.root() {
helloWorld()
}
And then check that everything worked as expected:
assert handler.log == 'Start Element: root, Start Element: helloWorld, End Element: helloWorld, End Element: root, '
8.2.4. StaxBuilder
A Groovy builder that works with Streaming API for XML (StAX) processors.
Here is a simple example using the StAX implementation of Java to generate XML:
def factory = javax.xml.stream.XMLOutputFactory.newInstance()
def writer = new StringWriter()
def builder = new groovy.xml.StaxBuilder(factory.createXMLStreamWriter(writer))
builder.root(attribute:1) {
elem1('hello')
elem2('world')
}
assert writer.toString() == '<?xml version="1.0" ?><root attribute="1"><elem1>hello</elem1><elem2>world</elem2></root>'
An external library such as Jettison can be used as follows:
@Grab('org.codehaus.jettison:jettison:1.3.3')
import org.codehaus.jettison.mapped.*
def writer = new StringWriter()
def mappedWriter = new MappedXMLStreamWriter(new MappedNamespaceConvention(), writer)
def builder = new groovy.xml.StaxBuilder(mappedWriter)
builder.root(attribute:1) {
elem1('hello')
elem2('world')
}
assert writer.toString() == '{"root":{"@attribute":"1","elem1":"hello","elem2":"world"}}'
8.2.5. DOMBuilder
A builder for parsing HTML, XHTML and XML into a W3C DOM tree.
For example this XML String
:
String recordsXML = '''
<records>
<car name='HSV Maloo' make='Holden' year='2006'>
<country>Australia</country>
<record type='speed'>Production Pickup Truck with speed of 271kph</record>
</car>
<car name='P50' make='Peel' year='1962'>
<country>Isle of Man</country>
<record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg in weight</record>
</car>
<car name='Royale' make='Bugatti' year='1931'>
<country>France</country>
<record type='price'>Most Valuable Car at $15 million</record>
</car>
</records>'''
Can be parsed into a DOM tree with a DOMBuilder
like this:
def reader = new StringReader(recordsXML)
def doc = groovy.xml.DOMBuilder.parse(reader)
And then processed further e.g. by using DOMCategory:
def records = doc.documentElement
use(groovy.xml.dom.DOMCategory) {
assert records.car.size() == 3
}
8.2.6. NodeBuilder
NodeBuilder
is used for creating nested trees of Node objects for handling arbitrary data.
To create a simple user list you use a NodeBuilder
like this:
def nodeBuilder = new NodeBuilder()
def userlist = nodeBuilder.userlist {
user(id: '1', firstname: 'John', lastname: 'Smith') {
address(type: 'home', street: '1 Main St.', city: 'Springfield', state: 'MA', zip: '12345')
address(type: 'work', street: '2 South St.', city: 'Boston', state: 'MA', zip: '98765')
}
user(id: '2', firstname: 'Alice', lastname: 'Doe')
}
Now you can process the data further, e.g. by using GPath expressions:
assert userlist.user.@firstname.join(', ') == 'John, Alice'
assert userlist.user.find { it.@lastname == 'Smith' }.address.size() == 2
8.2.7. JsonBuilder
Groovys JsonBuilder
makes it easy to create Json. For example to create this Json string:
String carRecords = '''
{
"records": {
"car": {
"name": "HSV Maloo",
"make": "Holden",
"year": 2006,
"country": "Australia",
"record": {
"type": "speed",
"description": "production pickup truck with speed of 271kph"
}
}
}
}
'''
you can use a JsonBuilder
like this:
JsonBuilder builder = new JsonBuilder()
builder.records {
car {
name 'HSV Maloo'
make 'Holden'
year 2006
country 'Australia'
record {
type 'speed'
description 'production pickup truck with speed of 271kph'
}
}
}
String json = JsonOutput.prettyPrint(builder.toString())
We use JsonUnit to check that the builder produced the expected result:
JsonAssert.assertJsonEquals(json, carRecords)
8.2.8. StreamingJsonBuilder
Unlike JsonBuilder
which creates a data structure in memory, which is handy in those situations where you want to alter the structure programmatically before output,
StreamingJsonBuilder
directly streams to a writer without any intermediate memory data structure.
If you do not need to modify the structure and want a more memory-efficient approach, use StreamingJsonBuilder
.
The usage of StreamingJsonBuilder
is similar to JsonBuilder
. In order to create this Json string:
String carRecords = '''
{
"records": {
"car": {
"name": "HSV Maloo",
"make": "Holden",
"year": 2006,
"country": "Australia",
"record": {
"type": "speed",
"description": "production pickup truck with speed of 271kph"
}
}
}
}
'''
you use a StreamingJsonBuilder
like this:
StringWriter writer = new StringWriter()
StreamingJsonBuilder builder = new StreamingJsonBuilder(writer)
builder.records {
car {
name 'HSV Maloo'
make 'Holden'
year 2006
country 'Australia'
record {
type 'speed'
description 'production pickup truck with speed of 271kph'
}
}
}
String json = JsonOutput.prettyPrint(writer.toString())
We use JsonUnit to check the expected result:
JsonAssert.assertJsonEquals(json, carRecords)
8.2.9. SwingBuilder
SwingBuilder
allows you to create full-fledged Swing GUIs in a declarative and concise fashion. It accomplishes this by employing a common idiom in Groovy, builders.
Builders handle the busywork of creating complex objects for you, such as instantiating children, calling Swing methods, and attaching these children to their parents.
As a consequence, your code is much more readable and maintainable, while still allowing you access to the full range of Swing components.
Here’s a simple example of using SwingBuilder
:
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
count = 0
new SwingBuilder().edt {
frame(title: 'Frame', size: [300, 300], show: true) {
borderLayout()
textlabel = label(text: 'Click the button!', constraints: BL.NORTH)
button(text:'Click Me',
actionPerformed: {count++; textlabel.text = "Clicked ${count} time(s)."; println "clicked"}, constraints:BL.SOUTH)
}
}
Here is what it will look like:
This hierarchy of components would normally be created through a series of repetitive instantiations, setters, and finally attaching this child to its respective parent.
Using SwingBuilder
, however, allows you to define this hierarchy in its native form, which makes the interface design understandable simply by reading the code.
The flexibility shown here is made possible by leveraging the many programming features built-in to Groovy, such as closures, implicit constructor calling, import aliasing, and string interpolation.
Of course, these do not have to be fully understood in order to use SwingBuilder
; as you can see from the code above, their uses are intuitive.
Here is a slightly more involved example, with an example of SwingBuilder
code re-use via a closure.
import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*
def swing = new SwingBuilder()
def sharedPanel = {
swing.panel() {
label("Shared Panel")
}
}
count = 0
swing.edt {
frame(title: 'Frame', defaultCloseOperation: JFrame.EXIT_ON_CLOSE, pack: true, show: true) {
vbox {
textlabel = label('Click the button!')
button(
text: 'Click Me',
actionPerformed: {
count++
textlabel.text = "Clicked ${count} time(s)."
println "Clicked!"
}
)
widget(sharedPanel())
widget(sharedPanel())
}
}
}
Here’s another variation that relies on observable beans and binding:
import groovy.swing.SwingBuilder
import groovy.beans.Bindable
class MyModel {
@Bindable int count = 0
}
def model = new MyModel()
new SwingBuilder().edt {
frame(title: 'Java Frame', size: [100, 100], locationRelativeTo: null, show: true) {
gridLayout(cols: 1, rows: 2)
label(text: bind(source: model, sourceProperty: 'count', converter: { v -> v? "Clicked $v times": ''}))
button('Click me!', actionPerformed: { model.count++ })
}
}
@Bindable is one of the core AST Transformations. It generates all the required boilerplate code to turn a simple bean into an observable one. The bind()
node creates appropriate PropertyChangeListeners
that will update the interested parties whenever a PropertyChangeEvent
is fired.
8.2.10. AntBuilder
Despite being primarily a build tool, Apache Ant is
a very practical tool for manipulating files including zip files, copy, resource processing, …
But if ever you’ve been working with a build.xml
file or some Jelly script
and found yourself a little restricted by all those pointy brackets, or
found it a bit weird using XML as a scripting language and wanted
something a little cleaner and more straight forward, then maybe Ant
scripting with Groovy might be what you’re after.
Groovy has a helper class called AntBuilder
which makes the scripting
of Ant tasks really easy; allowing a real scripting language to be used
for programming constructs (variables, methods, loops, logical
branching, classes etc). It still looks like a neat concise version of
Ant’s XML without all those pointy brackets; though you can mix and
match this markup inside your script. Ant itself is a collection of jar
files. By adding them to your classpath, you can easily use them within
Groovy as is. We believe using AntBuilder
leads to more concise and
readily understood syntax.
AntBuilder
exposes Ant tasks directly using the convenient builder notation that
we are used to in Groovy. Here is the most basic example, which is printing a message
on the standard output:
def ant = new AntBuilder() (1)
ant.echo('hello from Ant!') (2)
| 1 | creates an instance of AntBuilder |
| 2 | executes the echo task with the message in parameter |
Imagine that you need to create a ZIP file:
def ant = new AntBuilder()
ant.zip(destfile: 'sources.zip', basedir: 'src')
In the next example, we demonstrate the use of AntBuilder
to copy a list of files
using a classical Ant pattern directly in Groovy:
// lets just call one task
ant.echo("hello")
// here is an example of a block of Ant inside GroovyMarkup
ant.sequential {
echo("inside sequential")
def myDir = "target/AntTest/"
mkdir(dir: myDir)
copy(todir: myDir) {
fileset(dir: "src/test") {
include(name: "**/*.groovy")
}
}
echo("done")
}
// now lets do some normal Groovy again
def file = new File(ant.project.baseDir,"target/AntTest/groovy/util/AntTest.groovy")
assert file.exists()
Another example would be iterating over a list of files matching a specific pattern:
// lets create a scanner of filesets
def scanner = ant.fileScanner {
fileset(dir:"src/test") {
include(name:"**/Ant*.groovy")
}
}
// now lets iterate over
def found = false
for (f in scanner) {
println("Found file $f")
found = true
assert f instanceof File
assert f.name.endsWith(".groovy")
}
assert found
Or execute a JUnit test:
// lets create a scanner of filesets
ant.junit {
test(name:'groovy.util.SomethingThatDoesNotExist')
}
We can even go further by compiling and executing a Java file directly from Groovy:
ant.echo(file:'Temp.java', '''
class Temp {
public static void main(String[] args) {
System.out.println("Hello");
}
}
''')
ant.javac(srcdir:'.', includes:'Temp.java', fork:'true')
ant.java(classpath:'.', classname:'Temp', fork:'true')
ant.echo('Done')
It is worth mentioning that AntBuilder
is included in Gradle, so you can use it in Gradle
just like you would in Groovy. Additional documentation can be found in the
Gradle manual.
8.2.12. ObjectGraphBuilder
ObjectGraphBuilder
is a builder for an arbitrary graph of beans that
follow the JavaBean convention. It is in particular useful for creating test data.
Let’s start with a list of classes that belong to your domain:
package com.acme
class Company {
String name
Address address
List employees = []
}
class Address {
String line1
String line2
int zip
String state
}
class Employee {
String name
int employeeId
Address address
Company company
}
Then using ObjectGraphBuilder
building a Company
with three employees is as
easy as:
def builder = new ObjectGraphBuilder() (1)
builder.classLoader = this.class.classLoader (2)
builder.classNameResolver = "com.acme" (3)
def acme = builder.company(name: 'ACME') { (4)
3.times {
employee(id: it.toString(), name: "Drone $it") { (5)
address(line1:"Post street") (6)
}
}
}
assert acme != null
assert acme instanceof Company
assert acme.name == 'ACME'
assert acme.employees.size() == 3
def employee = acme.employees[0]
assert employee instanceof Employee
assert employee.name == 'Drone 0'
assert employee.address instanceof Address
| 1 | creates a new object graph builder |
| 2 | sets the classloader where the classes will be resolved |
| 3 | sets the base package name for classes to be resolved |
| 4 | creates a Company instance |
| 5 | with 3 Employee instances |
| 6 | each of them having a distinct Address |
Behind the scenes, the object graph builder:
-
will try to match a node name into a
Class
, using a defaultClassNameResolver
strategy that requires a package name -
then will create an instance of the appropriate class using a default
NewInstanceResolver
strategy that calls a no-arg constructor -
resolves the parent/child relationship for nested nodes, involving two other strategies:
-
RelationNameResolver
will yield the name of the child property in the parent, and the name of the parent property in the child (if any, in this case,Employee
has a parent property aptly namedcompany
) -
ChildPropertySetter
will insert the child into the parent taking into account if the child belongs to aCollection
or not (in this caseemployees
should be a list ofEmployee
instances inCompany
).
-
All 4 strategies have a default implementation that work as expected if the code follows the usual conventions for writing JavaBeans. In case any of your beans or objects do not follow the convention you may plug your own implementation of each strategy. For example imagine that you need to build a class which is immutable:
@Immutable
class Person {
String name
int age
}
Then if you try to create a Person
with the builder:
def person = builder.person(name:'Jon', age:17)
It will fail at runtime with:
Cannot set readonly property: name for class: com.acme.Person
Fixing this can be done by changing the new instance strategy:
builder.newInstanceResolver = { Class klazz, Map attributes ->
if (klazz.isAnnotationPresent(Immutable)) {
def o = klazz.newInstance(attributes)
attributes.clear()
return o
}
klazz.newInstance()
}
ObjectGraphBuilder
supports ids per node, meaning
that you can store a reference to a node in the builder. This is
useful when multiple objects reference the same instance. Because a
property named id
may be of business meaning in some domain models
ObjectGraphBuilder
has a strategy named IdentifierResolver
that you
may configure to change the default name value. The same may
happen with the property used for referencing a previously saved
instance, a strategy named ReferenceResolver
will yield the
appropriate value (default is `refId'):
def company = builder.company(name: 'ACME') {
address(id: 'a1', line1: '123 Groovy Rd', zip: 12345, state: 'JV') (1)
employee(name: 'Duke', employeeId: 1, address: a1) (2)
employee(name: 'John', employeeId: 2 ){
address( refId: 'a1' ) (3)
}
}
| 1 | an address can be created with an id |
| 2 | an employee can reference the address directly with its id |
| 3 | or use the refId attribute corresponding to the id of the corresponding address |
Its worth mentioning that you cannot modify the properties of a referenced bean.
8.2.13. JmxBuilder
See Working with JMX - JmxBuilder for details.
8.2.14. FileTreeBuilder
FileTreeBuilder is a builder for generating a file directory structure from a specification. For example, to create the following tree:
src/ |--- main | |--- groovy | |--- Foo.groovy |--- test |--- groovy |--- FooTest.groovy
You can use a FileTreeBuilder
like this:
tmpDir = File.createTempDir()
def fileTreeBuilder = new FileTreeBuilder(tmpDir)
fileTreeBuilder.dir('src') {
dir('main') {
dir('groovy') {
file('Foo.groovy', 'println "Hello"')
}
}
dir('test') {
dir('groovy') {
file('FooTest.groovy', 'class FooTest extends GroovyTestCase {}')
}
}
}
To check that everything worked as expected we use the following `assert`s:
assert new File(tmpDir, '/src/main/groovy/Foo.groovy').text == 'println "Hello"'
assert new File(tmpDir, '/src/test/groovy/FooTest.groovy').text == 'class FooTest extends GroovyTestCase {}'
FileTreeBuilder
also supports a shorthand syntax:
tmpDir = File.createTempDir()
def fileTreeBuilder = new FileTreeBuilder(tmpDir)
fileTreeBuilder.src {
main {
groovy {
'Foo.groovy'('println "Hello"')
}
}
test {
groovy {
'FooTest.groovy'('class FooTest extends GroovyTestCase {}')
}
}
}
This produces the same directory structure as above, as shown by these `assert`s:
assert new File(tmpDir, '/src/main/groovy/Foo.groovy').text == 'println "Hello"'
assert new File(tmpDir, '/src/test/groovy/FooTest.groovy').text == 'class FooTest extends GroovyTestCase {}'


AGG Learning material
Follow along with the lesson plans here in order to learn how to create and edit webmaps. The lessons are meant to be followed in order as they build upon one another, but it is not necessary.
Lesson 1
This is the first lesson of the project. The intent of this lesson is to provide you with a basic handle on how to create a webmap and to understand the functions of the different components that make up a webmap.
Lesson 2
TODO
Lesson 3
TODO
Support or Contact
Having trouble with lessons or want to suggest new lessons? Create an issue on our github page and we’ll help you sort it out or contact you for more info on your lesson idea.


how much adaptive compression is occurring in the RiOS data store using legacy mode. The report combines the percentages due to both local and remote adaptive compression (as signaled by the peers). the percentage of the traffic, in bytes, that is adapted to in-memory-only (or transient), compared to the total SDR traffic (SDR-adaptive mode). The report contains these statistics that summarize RiOS data store adaptive compression activity, shown as a percent of total SDR data.Note: You must enable the SDR-Adaptive setting before creating this report. For details, see Setting an Adaptive Streamlining Mode.
What is the relative adaptive compression when SDR-Adaptive is enabled at various times of the day?
1.
Select a report time interval of 5 minutes (5m), 1 hour (1h), 1 day (1d), 1 week (1w), All, or type a custom date. All includes statistics for the last 30 days.You can view the newest data and see data points as they are added to the chart dynamically. To display the newest data, click Show newest data.


Editing the Target Language Recording¶
See this File https://github.com/unfoldingWord-dev/translationRecorder-Info/blob/master/IconsChecking.pdf for the list of icons and their name.
Compare the recording to the Source Language recording¶
- To compare your recording to the Source Language recording press the hearing ear icon and press the play icon on the gray bar.
- To pause the recording tap the pause button on the gray bar (the pause icon replaces the play icon.)
- To rewind (go towards the beginning of the recording) or fast forward (go towards the end of the recording) press and hold the green dot and slide your finger to the left for rewind or to the right to fast forward.
- To return to your recording press the wave button.
Remove a section of recording¶
- Line up the thin yellow line where you want to start removing some of the recording.
Note: The yellow line does not move. • Press-and-hold to move the recording to the yellow line. • Press the flag icon. This will insert a marker where the cut will start.
2. Set the ending point of the cut. • Drag the recording by holding your finger on the screen and sliding to the left until you reach the end of the part to be removed. • Tap the flag button. This will mark the section for deletion.
Optional: Tap the play icon to listen to the section that will be removed.
3. Delete the selected recording. * Tap on the scissors icon to delete the selected recording. * Tap on the back arrow to undo the last edit.
Insert a new section of recording.¶
- Line up the thin yellow line where you want the recording to be inserted.
- Tap the Add a Recording icon. This will open a new recording session.
- Tap the microphone icon to start recording.
- When finished, tap the pause icon.
- To insert the new recording, tap the checkmark icon.
- A pop up will appear stating it is inserting recording…please wait.
- The original target language recording opens with the added recording.
To save the file tap the save icon. * A ‘Saving’ pop-up shows.
Once it is done saving it will open the file manager with your most recent file on top.
Rate the Target Language Recording¶
If the recording is done well, then add a star rating to the recording.
Tap on the star icon in the top gray bar. The ‘Rate this take’ window opens.
- The term “take” is another word for a recording.
Tap on one of the three stars to rate.
- The star on the left for a 1-star rating – meaning this is a good recording. The star turns red
- The middle star for a 2-star rating – meaning this is a better recording. The stars turn yellow.
- The star on the right for a 3-star rating – meaning this is an excellent recording. The stars turn green.
Tap on ‘OK’ to save the rating.


game name: {{game.gameName}}
description: {{game.description}}
node count: {{game.nodeCount}}
Rating: {{game.avgRating}} stars {{game.numOfRatings}} reviews
Rating: no reviews
created date: {{game.createdDate}}


Domain Facade
Putting it all together
Directory Structure
Modify the current directory structure as follows in your project directory.
|- MyProjectDirectory
| |- DomainLayer
| | |- Connections
| | | |- MyProjectSQLConnection.cs
| | |- Models
| | | |- Data
| | | | |- SampleDataModel.cs
| | | |- Parameter
| | | | |- GetSampleDataParameters.cs
| | |- Methods
| | | |- MyProjectSQLMethods.cs
| | |- IDomainFacade.cs
| | |- DomainFacade.cs
Add Domain Facade class
Create a IDomainFacade.cs
interface file in MyProjectDirectory/DomainLayer
as follows:
public interface IDomainFacade
{
public IDbResponse<SampleDataModel> GetSampleData(GetSampleDataParameters parameters);
}
Create a DomainFacade
class file in MyProjectDirectory/DomainLayer
as follows:
internal class DomainFacade: IDomainFacade
{
public DomainFacade(){
string connectionString = "MyConnectionString"; // Get this value from a configuration source in real code;
// MyProjectSQLConnection must be registered before any calls can be made
MyProjectSQLConnection.RegisterConnection(string connectionString);
}
public IDbResponse<SampleDataModel> GetSampleData(GetSampleDataParameters parameters)
=> MyProjectSQLMethods.GetSampleData.Execute(parameters);
}
Using Domain Facade
You may now use
public class MyClass
{
private IDomainFacade DomainFacade {get; set;}
public MyClass(){
DomainFacade = new DomainFacade();
}
public void DoSomething(){
var results = DomainFacade.GetSampleData(new GetSampleDataParameters(){
Guid = Guid.NewGuid(), // use a real Guid here not a new one( this is example only)
String = "Some string value"
});
if(results.HasError){
Exception error = result.Error;
// Uh Oh! Need to handle error result.
}else{
// Everything is Good!
}
}
}
Recomendations
Since your project code will likely call the DomainFacade object many times consider creating a global instance of it in your project. In Core projects this can be done with dependancy injection.
Core Specific Notes
When using the Core version of this library you may need to include some extra code in Startup.cs
to configure the connection strings.
Please consult the official .NET Core doumentation about adding Connection strings for the latest information.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddConnectionStrings(connectionStrings =>
{
connectionStrings.MySQLConnectionString = connectionStrings.GetSqlConnection(
Configuration.GetConnectionString("MySQLConnectionString"),
Configuration["MySQLConnectionString:ProviderName"],
builder => {
builder.UserID = Configuration["MySQLConnectionString:UserID"];
builder.Password = Configuration["MySQLConnectionString:Password"];
});
});
...
}


Open Systems Technologies Bitcamp
Hosting
Hi, I'm Brian
Let's talk hosting, or:
how to put your site on the web.
Two Parts
Domain Name
ostusa.com
Server Space
Consider...
Using a "smart" phone, how do you make phone calls these days?
Find a contact by their name/picture
Tap person, phone dials their number.
The story of a web request
What actually happens when you request a web page?
Step 1: Enter a URL
Includes a domain name
(Find a contact)
Step 2: Browser Resolves Domain
(Phone translates contact to number)
Step 3: Browser Requests Page from Web Server
(Call starts)
Step 4: Browser starts rendering Page
(Conversation!)
Terms
Some terms before we get too far.
-
Browser
A program on a device intended to display web pages.
-
Web Server
A computer on the internet tasked with delivering pages.
-
URL
Uniform Resource Locator - a reference to a specific page on a specific domain/IP over a specific protocol.
https :// www.girldevelopit.com / about
-
Domain Name
A human-friendly reference to a device on the internet.
-
IP Address
A computer-friendly reference to a device on the internet.
Register a Domain Name
that is, rent space in the internet's address book
- Pick a domain name
- Register with a registrar
- Point your domain name at your server
Find some Server Space
Probably what one thinks about when planning hosting.
Can host through employers, but for our situation, host via hosting companies
Provided with remote management tools.
- SSH/SFTP
- FTP
- Web portals
- Deployment hooks
All ways to get your web files up to the chosen server.
Using Hosts
Ok, so what does that look like?
Using Hosts
Ok, so what does that look like? (example)
Using Hosts
Ok, so what does that look like?
Types of Hosting
- Shared:
- You share a server with multiple customers.
- VPS:
- You have full administrator access to a slice of a server.
- Dedicated:
- You have full admin access to an entire server.
- Cloud:
- A modern variant of VPS hosting. Often used and paid by-the-hour.
- Colocation:
- You have full admin access to an entire server.
- Manage:
- Usually a luxury version of dedicated hosting.
What to look for
http://www.webhostingtalk.com
- uptime
- cost
- server software (Apache / nginx / IIS)
- platform (PHP / .NET / NodeJS, etc)
- no additional charges for additional domains
- 24/7 support from people who speak your language
- scalable service, in case you get slashdotted
- sane, automatic handling of subdomains
Some (Personal) Recommendataions
Simple Shared Hosting
VPS
Platform As a Service


Created by Luis Ibanez / @luisibanez
“ An Act for preventing the frequent Abuses in printing seditious treasonable and unlicensed Bookes and Pamphlets and for regulating of Printing and Printing Presses. ”
“ An Act for the Encouragement of Learning, by Vesting the Copies of Printed Books in the Authors or Purchasers of such Copies, during the Times therein mentioned.  ”


Terms of Service
Terms of Service Dated: August 9, 2020 You must agree to the Media Player addon's
privacy policy.
I agree


Toggle navigation
List Animals
Become Foster Parents
About Us
Dropdown
Post Animal Story
Edit my Profile
Update my animals
Logout
Animal Rescue Stories
Upload Main Image
Select Animal
New animal
rover
Name
Animal Type:
select...
Dog
Animal Breed:
select...
Collie
Age:
Weight:
Gender:
Male
Female
Available Adoption Date
.tumblr.com
Animal's Rescue Story
Care and Vaccination info
Save
Clear


Reactive Programming
Introduction
Hot versus cold observables
Unicast versus multicast observables
Observables-subjects
Subject
BehavioralSubject
ReplaySubject
AsyncSubject


- PersistentObject - Class in bo
-
Serializable class that can be used
to store a collection of PopulationRecords.
- PersistentObject() - Constructor for class bo.PersistentObject
-
Default class constructor.
- PersistentObject(String) - Constructor for class bo.PersistentObject
-
Overloaded constructor that can be used to
load the PopulationRecords.
- PersistentObjectWriter - Class in io
-
Wrapper class for the process used to
Serialize the Persistent Object class.
- PersistentObjectWriter(String[], PersistentObject) - Constructor for class io.PersistentObjectWriter
-
- POPESTIMATE2010_INDEX - Static variable in class db.PopulationTable
-
- POPESTIMATE2010_INDEX - Static variable in class db.PopulationTableModel
-
- POPESTIMATE2011_INDEX - Static variable in class db.PopulationTable
-
- POPESTIMATE2011_INDEX - Static variable in class db.PopulationTableModel
-
- popPerIncr(int) - Method in class bo.Record
-
Implementation of the RecordAnalytics.popPerIncr Method.
- popPerIncr(int) - Method in interface bo.RecordAnalytics
-
Population increase percentage.
- PopulationRecord - Class in bo
-
Sub class that extends the abstract Record class.
- PopulationRecord() - Constructor for class bo.PopulationRecord
-
Class constructor.
- PopulationRecord(String[]) - Constructor for class bo.PopulationRecord
-
Overloaded class constructor that
accepts a string array of values.
- PopulationTable - Class in db
-
Class intended to virtualize
the Population_T database table.
- PopulationTable() - Constructor for class db.PopulationTable
-
Class Constructor
- PopulationTable(ArrayList<PopulationRecord>) - Constructor for class db.PopulationTable
-
Overloaded constructor that will initialize the target Population_T
table using a collection of PopulationRecords.
- PopulationTableModel - Class in db
-
This class used virtualize values stored
in the PopulationTable Class.
- PopulationTableModel(String[], String[], ArrayList<PopulationRecord>) - Constructor for class db.PopulationTableModel
-
Class constructor.
- Program - Class in <Unnamed>
-
Main Program thread.
- Program() - Constructor for class Program
-