Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Kenneth A. Kousen - Making Java Groovy - 2014.pdf
Скачиваний:
50
Добавлен:
19.03.2016
Размер:
15.36 Mб
Скачать

Accessing Google Chart Tools

19

2.1Hello, Groovy

Because every programming language book is required by law to include a “Hello, World!” program, here’s Groovy’s version:

println 'Hello, World!'

In Java you compile with javac and execute the resulting bytecodes with java. In Groovy you can compile with groovyc and execute with groovy, but you don’t actually have to compile first. The groovy command can run with a source code argument, and it will compile first and then execute. Groovy is a compiled language, but you don’t have to separate the steps, though most people do. When you use an IDE, for example, every time you save a Groovy script or class, it is compiled.

The single line shown earlier is a complete program. Unlike with Java, you don’t need to put all Groovy code into a class. Groovy supports running scripts. Everything is still Java bytecodes under the hood, so what happens is that Groovy scripts eventually become the body of the main method in a class that extends groovy.lang.Script.

Note two additional differences in syntax between Groovy and Java:

Semicolons are optional. You can add them, and it’s appropriate to use them if you have more than one statement on a line, but they’re not normally necessary.

Parentheses are often optional. The println command is actually a method call, and the String is the argument to the method. Because there’s no ambiguity, you can leave out the parentheses. It’s not wrong to include them, though, if you want.

OPTIONAL PARENTHESES Parentheses are optional until they aren’t. Simple method calls normally omit them, but if there’s any uncertainty, add them. Groovy is all about simplicity and understandability.

Now that the “Hello, World!” example is out of the way, I can move on to something a bit more interesting. One helpful use case for Groovy is that it makes a nice client for RESTful web services like Google Chart.

2.2Accessing Google Chart Tools

One of the APIs that Google makes available is a RESTful web service known as the Chart API, or, more formally, Google Chart Tools Image API.1 The documentation is located at https://developers.google.com/chart/image/. The chart tools provide a rich API for JavaScript users, but the inputs are ultimately URLs with query parameters.

A developer sends a request to the base URL https://chart.apis.google.com/chart and appends query parameters to specify the type of chart, its size, the data, and any

1Google officially deprecated the image charts portion of Google Chart Tools on April 20, 2012. As of summer, 2013, the API still works. It is used here both as a nice, self-contained example and as a simple application that illustrates many Groovy features. Other examples of accessing publicly available services are given throughout the book.

www.it-ebooks.info

Figure 2.1 The Google Chart API “Hello, World” example

20

CHAPTER 2 Groovy by example

labels. Because that API also needs a “Hello, World” example, here’s the URL for a three-dimensional pie chart:

https://chart.apis.google.com/chart?

cht=p3&

chs=250x100&

chd=t:60,40&

chl=Hello|World

This URL would be all on one line but is written out here (and in the documentation) for illustration purposes. After the base URL, the parameters list the chart type (cht) as a 3D pie chart, the chart size (chs) as 250 by 100 pixels, the chart data (chd) as 60 and 40 in simple text format, and the chart labels (chl) “Hello” and “World.” Type that URL into a browser and the resulting image is returned, as shown in figure 2.1.

The URL shown is hard-wired to produce the chart in figure 2.1. To make this more general, I’ll show how to produce the URL from strings, lists, maps, closures, and builders.

GOAL Write a Groovy script to generate the “Hello, World” 3D pie chart as a desktop application.

In the process, I’ll discuss

String manipulation

Lists and maps

Processing data using closures

Groovy builder classes

In this case I’ll implement the steps in a simple script; later, it could be converted to a class for integration purposes.

2.2.1Assembling the URL with query string

To start, I need a variable to represent the base URL. In a Groovy script you don’t actually have to declare any types at all. If you declare a type the variable becomes local to the script. If not, it becomes part of the “binding,” which is discussed in the next chapter. Here, because I know the URL will be contained in a string before I convert it, I’ll declare the variable to be of type java.lang.String:

String base = 'http://chart.apis.google.com/chart?'

Groovy is optionally typed. This means you can specify a type if you want to, or you can use the keyword def if you don’t know or care. There’s some debate among developers about when to use def and when to specify a type. Dierk Koenig, lead author on the superb Groovy in Action (Manning, 2007), says it this way:

www.it-ebooks.info

Accessing Google Chart Tools

21

USING DEF If you think of a type, type it (from Dierk Koenig). In other words, if you know a variable will be a String, or a Date, or an Employee, use that type of variable.

In my own experience, I used to use def a lot, but as time goes by I use it less and less. I agree with Dierk, with the addition that when I’m tempted to use def I often pause a moment and try to think of an actual type before using it. Other developers have other styles, though. That’s the beauty of an optionally typed language: there’s room for everybody.

I now need to append the query parameters to this URL. Rather than write the query string directly I’m going to use a typical idiom for this type of application, which is to build a map and then generate the query string from the map parameters. With that in mind, here’s the map of parameters:

def params = [cht:'p3',chs:'250x100', chd:'t:60,40',chl:'Hello|World']

In Groovy you create a map with square brackets, and each entry consists of keys and values separated by a colon. The keys are assumed to be strings by default. The values can be anything. By default, the params variable is an instance of java.util

.LinkedHashMap.

COLLECTIONS Groovy has native syntax for lists and maps. Map keys are assumed to be strings.

Each corresponding value is surrounded by single quotes. In Groovy, single-quoted strings are instances of java.lang.String. Double-quoted strings are “interpolated” strings, known (unfortunately) as GStrings. I’ll show an example of string interpolation later in this program.

To transform the map into a query string I first need to convert each of the map entries into strings of the form “key=value,” and then I need to concatenate them all together using ampersands as separators.2 The first step is accomplished by using a special method added to all Groovy collections, known as collect. The collect method takes a closure as an argument, applies the closure to each element of the collection, and returns a new collection containing the results.

Closures are introduced in the next sidebar and discussed extensively throughout the book, but for the moment think of them as blocks of code representing the body of a function, which may take dummy arguments. In the case of collect, when applied to a map, the closure can take either one or two arguments. If the closure takes one argument, the argument represents a Map.Entry; with two arguments, the first is the key and the second is the value for each entry.

2I also need to URL-encode the map entries, but in this case they’re already fine. In other examples of RESTful web services I’ll demonstrate the encoding process.

www.it-ebooks.info

22

CHAPTER 2 Groovy by example

To transform the map into a list of key=value pairs, the following two-argument closure works in the collect method:

params.collect { k,v -> "$k=$v" }

In Groovy, if the last argument to any method is a closure you can put the closure outside the parentheses. In this case the only argument to collect is a closure, so even the optional parentheses are omitted.

What is a closure?

A closure is a block of code, delimited by curly braces, which can be treated as an object. The arrow notation is used to specify dummy arguments. In the closure applied to the map in the current example, the two dummy arguments are k and v, which represent the key and value of each entry. The expression on the right side of the arrow says to substitute each key and value into a GString separated by an equals sign. This collect method takes each entry in the map and converts it into a string with the key assigned to the value, and produces a list of results.

The result of the operation is shown here:

["cht=p3", "chs=250x100", "chd=t:60,40", "chl=Hello|World"]

This process is illustrated in figure 2.2.

To create the query string, use another method added by Groovy to collections, called join. The join method takes a single argument that’s used as the separator when assembling the elements into a string. To create a query string, invoke join with an ampersand as an argument:

["cht=p3", "chs=250x100", "chd=t:60,40", "chl=Hello|World"].join('&')

The result is the needed query string, as shown here:

"cht=p3&chs=250x100&chd=t:60,40&chl=Hello|World"

Here’s the entire process so far, taking the base URL and the parameter map, and building the Google Chart URL:

String base = 'http://chart.apis.google.com/chart?' def params = [cht:'p3',chs:'250x100',

chd:'t:60,40',chl:'Hello|World']

String qs = params.collect { k,v -> "$k=$v" }.join('&')

[cht:'p3', chs:'250x100', chd:'t:60,40', chl:'Hello|World']

collect { k,v -> "$k=$v" }

["cht=p3", "chs=250x100", "chd=t:60,40", "chl=Hello|World"]

Figure 2.2 Apply collect to a map to convert it into a list, where each entry is transformed into a string.

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]