32
Groovy XML Processing Vladimir Forfutdinov

Groovy XML Processing with WebObjects

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Groovy XML Processing with WebObjects

Groovy XML ProcessingVladimir Forfutdinov

Page 2: Groovy XML Processing with WebObjects

• Java vs Groovy short cuts

• XML parsing with Groovy

• XML generating with Groovy

• How to access EO inside Groovy

Outline

Page 3: Groovy XML Processing with WebObjects

Java vs Groovy

• Java Virtual Machine thinks Groovy is Java

• Inspired by Python, Ruby and Smalltalk

• Java developers will have almost-zero learning curve

• Supports Domain-Specific Languages

• Powerful processing primitives, OO abilities and an Ant DSL

• Works with existing Java objects and libraries

Page 4: Groovy XML Processing with WebObjects

Setup

• Easy to find and learn at: http://groovy.codehaus.org/

• Eclipse plug-in at: http://groovy.codehaus.org/Eclipse+Plugin

• groovyShell

• groovy-all-1.7.0.jar

Page 5: Groovy XML Processing with WebObjects

Hello World!

//JAVAclass myfirstjavaprog{ public static void main(String args[]) { System.out.println("Hello World!"); }}

//GROOVYprintln "Hello World!"

//GROOVY command linegroovy -e "println 'Hello ' + args[0]" World!

GROOVY SCRIPT ARG 1

Page 6: Groovy XML Processing with WebObjects

Method call on a Null Object

//JAVAMyObject obj = nullif (obj != null){ return obj.getChildren().getFirst()} else { return null}

//GROOVYMyObject obj = nullreturn obj?.getChildren()?.getFirst()

Page 7: Groovy XML Processing with WebObjects

Closures

Functions that are first class objects - a chunk of code that can be passed around as if it were a string or an integer.

square = { it * it }

square(4)

//RESULT16

[ 1, 2, 3, 4 ].collect(square)

//RESULT[ 1, 4, 9, 16 ]

printMapClosure = { key, value -> println key + "\t= " + value }

[ "Name" : "John", "Address" : "Here", "Likes" : "WOWODC" ].each(printMapClosure)

//RESULTName = JohnAddress= HereLikes = WOWODC

Page 8: Groovy XML Processing with WebObjects

Meta Class - Methods

Intercepting Method Calls

class MyClass{ def hello(){ 'invoked hello directly' } def invokeMethod(String name, Object args){ return "unknown method $name(${args.join(', ')})" }}

def mine= new MyClass()

println mine.hello()

//RESULTinvoked hello directly

println mine.foo("Mark", 19)

//RESULTunknown method foo(Mark, 19)

Page 9: Groovy XML Processing with WebObjects

Meta Class - Properties

Intercepting Property Accesses

class MyClass{ def greeting = 'accessed greeting directly' Object getProperty(String property) { "read from property $property" } void setProperty(String property, Object newValue) { throw new Exception("wrote to property $property") }}def mine = new MyClass()

//try to read ‘greeting’ propertyprintln mine.greeting

//RESULTread from property greeting

//try to set ‘greeting’ propertytry { mine.greeting = 'hi' } catch(e) { println e.message }

//RESULTwrote to property greeting

//we can access a property directly using .@ syntaxprintln mine.@greeting

//RESULTaccessed greeting directly

Page 10: Groovy XML Processing with WebObjects

Meta Class - At Run-time

Adding new property and method to a class during Run-time

class A{}

//add new property ‘hi’A.metaClass.hi = 'Hi!!!'

def a1 = new A()

println a1.hi

//RESULTHi!!!

//add new method ‘hello’A.metaClass.hello = {-> "Hello!"}

def a2 = new A()

println a2.hello()

//RESULTHello!

Page 12: Groovy XML Processing with WebObjects

XML Input sample

class XmlExamples { static def CAR_RECORDS = ''' <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> '''}

Page 13: Groovy XML Processing with WebObjects

XmlParser vs XmlSlurper

def records_p = new XmlParser().parseText(XmlExamples.CAR_RECORDS)def records_s = new XmlSlurper().parseText(XmlExamples.CAR_RECORDS)

def allRecords_p = records_p.car.size()assert allRecords_p == 3def allRecords_s = records_s.car.size()assert allRecords_s == 3

def allNodes = records_p.depthFirst().size()assert allNodes_p == 10def allNodes_s = records_s.depthFirst().collect{ it }.size()assert allNodes_s == 10

def firstRecord_p = records_p.car[0]def firstRecord_s = records_s.car[0]

assert 'car' == firstRecord_p.name()assert 'car' == firstRecord_s.name()

assert 'Holden' == firstRecord_p.'@make'assert 'Holden' == [email protected]()

assert 'Australia' == firstRecord_p.country.text()assert 'Australia' == firstRecord_s.country.text()

<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>

Page 14: Groovy XML Processing with WebObjects

XmlParser vs XmlSlurper

// 2 cars have an 'e' in the makeassert records_p.car.findAll{ it.'@make'.contains('e') }.size() == 2

// option 1assert records_s.car.findAll{ [email protected]().contains('e') }.size() == 2

// option 2assert records_s.car.findAll{ it.@make =~ '.*e.*' }.size() == 2

<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>

Page 15: Groovy XML Processing with WebObjects

XmlSlurper

println records.depthFirst().grep{ it.@type != '' }.'@type'*.text()//Result[speed, size, price]

println records.'**'.grep{ it.@type != '' }.'@type'*.text()//Result[speed, size, price]

def countryOne = records.car[1].countryprintln countryOne.parent()[email protected]()//ResultPeel

println countryOne.'..'[email protected]()//ResultPeel

// names of cars with records sorted by yearprintln records.car.list().sort{ [email protected]()}.'@name'*.text()//Result[Royale, P50, HSV Maloo]

// names of countries with ‘s’ in the nameprintln records.'**'.grep{ it.@type =~ 's.*' }*.parent().country*.text()//Result[Australia, Isle of Man]

<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>

Page 16: Groovy XML Processing with WebObjects

XmlSlurper

class XmlExamples { static def CF_MESSAGE = ''' <cf:Message xmlns:cf='http://controlsforce.com/schema/message.xsd'> <cf:Properties> <cf:Name>ck_mstr</cf:Name> <cf:Process>FREUDENBERG_DEMO</cf:Process> <cf:User></cf:User> <cf:Date>Fri Dec 25 17:37:55 EST 2009</cf:Date> <cf:MessageCount>0</cf:MessageCount> <cf:UID>uniqueId-0</cf:UID> </cf:Properties> </cf:Message> '''}

def xml = new XmlSlurper().parseText(XmlExamples.CF_MESSAGE)

xml.Properties.children().each { println "${it.name()} -> ${it.text()}" }

Name -> ck_mstrProcess -> FREUDENBERG_DEMOUser -> Date -> Fri Dec 25 17:37:55 EST 2009MessageCount -> 0UID -> uniqueId-0

Page 17: Groovy XML Processing with WebObjects

XML Generation

• Building XML using simple Java

• StreamingMarkupBuilder - A builder class for creating XML markup

Page 18: Groovy XML Processing with WebObjects

Java

//assuming we have a Writer created alreadywriter.write("<root>"); writer.write(“<a a1=‘one’>”); writer.write("<b>3 < 5</b>"); writer.write("<c a2=‘two’>blah</c>"); writer.write("<d>"); writer.write("<f>hello</f>"); writer.write("</d>"); writer.write("</a>");writer.write("</root>");

//Result<root> <a a1='one'> <b>3 &lt; 5</b> <c a2='two'>blah</c> <d> <f>hello</f> </d> </a></root>

Page 19: Groovy XML Processing with WebObjects

StreamingMarkupBuilder

import groovy.xml.StreamingMarkupBuilder

new StreamingMarkupBuilder().bind { root { a ( a1:'one' ) { b { mkp.yield( '3 < 5' ) } c ( a2:'two', 'blah' ) d { f (‘hello’) } } }}.toString()

//Result<root> <a a1='one'> <b>3 &lt; 5</b> <c a2='two'>blah</c> <d> <f>hello</f> </d> </a></root>

writer.write("<root>"); writer.write(“<a a1=‘one’>”); writer.write("<b>3 < 5</b>"); writer.write("<c a2=‘two’>blah</c>"); writer.write("<d>"); writer.write("<f>hello</f>"); writer.write("</d>"); writer.write("</a>");writer.write("</root>");

Page 20: Groovy XML Processing with WebObjects

StreamingMarkupBuilder

import groovy.xml.StreamingMarkupBuilder

def dic = ['a':123, 'b':456, 'c':949]

new StreamingMarkupBuilder().bind { root { dic.each { "${it.key}" (it.value) } }}.toString()

//Result<root> <a>123</a> <b>456</b> <c>949</c></root>

Page 21: Groovy XML Processing with WebObjects

StreamingMarkupBuilder

import groovy.xml.StreamingMarkupBuilder

def dic = ['a':['name':'apple', 'type':123], 'b':['name':'cheese', 'type':456], 'c':['name':'milk', 'type':949]]

new StreamingMarkupBuilder().bind { root { dic.each { "${it.key}" (it.value) } }}.toString()

//Result<root> <a name='apple' type='123'/> <b name='cheese' type='456'/> <c name='milk' type='949'/></root>

Page 22: Groovy XML Processing with WebObjects

EOs inside Groovy

• Setup

• Demo

Page 23: Groovy XML Processing with WebObjects

Setup

• Main Component with a set of tables that will list the data from each table

• Main.java replaced with Main.groovy (just for some extra fun)

• MySQL Database with three tables:

• Employee

• Manager

• Job

*0..1

*0..1

*0..1salary

name

manager

job

age

Employee

owner

name

employees

Job

name

jobs

employees

Manager

Page 24: Groovy XML Processing with WebObjects

DEMO

Page 25: Groovy XML Processing with WebObjects

Questions

Page 26: Groovy XML Processing with WebObjects

Bonus

Page 27: Groovy XML Processing with WebObjects

ConfigSlurper

• Utility class within Groovy for writing properties file

• Unlike regular Java properties files ConfigSlurper scripts support native Java types and are structured like a tree.

Page 28: Groovy XML Processing with WebObjects

Reading configuration with ConfigSlurper

def config = new ConfigSlurper().parse (configFile)//get the all of the config dataprintln config.WOWODC

//Result["Bonus":["testId":1, "testName":"Hello Bonus Test string"], "BonusList":["key1":"val1", "hi":"hello"]]

//get only the Bonus sectionprintln config.WOWODC.Bonus

//Result["testId":1, "testName":"Hello Bonus Test string"]

//get only the testId valueprintln config.WOWODC.Bonus.testId

//Result1

//list keys and values under BonusList sectionconfig.WOWODC.BonusList.each {println "${it.key} = ${it.value}"}

//Resultkey1 = val1hi = hello

def configFile = ''' WOWODC { Bonus { testId = 1 testName = "Hello Bonus Test string" }

BonusList { key1 = 'val1' hi = 'hello' } }'''

Page 29: Groovy XML Processing with WebObjects

Updating configuration with ConfigSlurper

//get the all of the config dataconfig.Hi.GoodBuy.say = 'Hello'

def sw = new StringWriter()println config?.writeTo(sw).toString()

//Result -->WOWODC { Bonus { testId=1 testName="Hello Bonus Test string" } BonusList { key1="val1" hi="hello" }}Hi.GoodBuy.say="Hello" // got updated

WOWODC { Bonus { testId = 1 testName = "Hello Bonus Test string" }

BonusList { key1 = 'val1' hi = 'hello' } }

Page 30: Groovy XML Processing with WebObjects

Updating configuration with ConfigSlurper

//get the all of the config dataconfig.Hi.GoodBuy.tell = 'Hi'

def sw = new StringWriter()println config?.writeTo(sw).toString()

//ResultWOWODC { Bonus { testId=1 testName="Hello Bonus Test string" } BonusList { key1="val1" hi="hello" }}Hi { GoodBuy { say="Hello" tell="Hi" // got updated }}

WOWODC { Bonus { testId=1 testName="Hello Bonus Test string" } BonusList { key1="val1" hi="hello" }}Hi.GoodBuy.say="Hello"

Page 31: Groovy XML Processing with WebObjects

Updating configuration with ConfigSlurper

//get the all of the config dataconfig.WOWODC.Bonus.testId = 2

def sw = new StringWriter()println config?.writeTo(sw).toString()

//Result -->WOWODC { Bonus { testId=2 // got updated testName="Hello Bonus Test string" } BonusList { key1="val1" hi="hello" }}Hi { GoodBuy { say="Hello" tell="Hi" }}

WOWODC { Bonus { testId=1 testName="Hello Bonus Test string" } BonusList { key1="val1" hi="hello" }}Hi { GoodBuy { say="Hello" tell="Hi" }}

Page 32: Groovy XML Processing with WebObjects

DEMO