SlideShare a Scribd company logo
1 of 32
Download to read offline
Groovy XML Processing
Vladimir Forfutdinov
Outline

•   Java vs Groovy short cuts
•   XML parsing with Groovy
•   XML generating with Groovy
•   How to access EO inside Groovy
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
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
Hello World!
//JAVA
class myfirstjavaprog
{
        public static void main(String args[])
        {
           System.out.println("Hello World!");
        }
}



//GROOVY
println "Hello World!"



//GROOVY command line
groovy -e "println 'Hello ' + args[0]" World!
                   GROOVY SCRIPT        ARG 1
Method call on a Null Object
//JAVA
MyObject obj = null
if (obj != null)
{
   return obj.getChildren().getFirst()
} else {
   return null
}



//GROOVY
MyObject obj = null
return obj?.getChildren()?.getFirst()
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)

//RESULT
16

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

//RESULT
Name	   = John
Address	= Here
Likes	 = WOWODC
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()

//RESULT
invoked hello directly

println mine.foo("Mark", 19)

//RESULT
unknown method foo(Mark, 19)
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’ property
println mine.greeting

//RESULT
read from property greeting

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

//RESULT
wrote to property greeting

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

//RESULT
accessed greeting directly
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

//RESULT
Hi!!!

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

def a2 = new A()

println a2.hello()

//RESULT
Hello!
XML Parsing


•   XmlParser - supports GPath expressions for XML documents


•   XmlSlurper - lower overheads than XmlParser due to lazy
    evaluation
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>
  '''
}
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 == 3
def allRecords_s = records_s.car.size()
assert allRecords_s == 3

def allNodes = records_p.depthFirst().size()
assert allNodes_p == 10
def allNodes_s = records_s.depthFirst().collect{ it }.size()
assert allNodes_s == 10                                           <records>
                                                                    <car name='HSV Maloo' make='Holden' year='2006'>
                                                                       <country>Australia</country>
def firstRecord_p = records_p.car[0]                                   <record type='speed'>
def firstRecord_s = records_s.car[0]                                  Production Pickup Truck with speed of 271kph
                                                                    </record>
                                                                    </car>
assert 'car' == firstRecord_p.name()                                <car name='P50' make='Peel' year='1962'>
                                                                       <country>Isle of Man</country>
assert 'car' == firstRecord_s.name()
                                                                       <record type='size'>
                                                                      Smallest Street-Legal Car at 99cm wide and 59 kg in weight
assert 'Holden' == firstRecord_p.'@make'                             </record>
                                                                    </car>
assert 'Holden' == firstRecord_s.@make.text()                       <car name='Royale' make='Bugatti' year='1931'>
                                                                       <country>France</country>
assert 'Australia' == firstRecord_p.country.text()                     <record type='price'>
                                                                      Most Valuable Car at $15 million
assert 'Australia' == firstRecord_s.country.text()                  </record>
                                                                    </car>
                                                                  </records>
XmlParser vs XmlSlurper
// 2 cars have an 'e' in the make
assert records_p.car.findAll{ it.'@make'.contains('e') }.size() == 2

// option 1
assert records_s.car.findAll{ it.@make.text().contains('e') }.size() == 2

// option 2
assert 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>
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].country
println countryOne.parent().@make.text()
//Result
Peel
                                                                      <records>
println countryOne.'..'.@make.text()                                    <car name='HSV Maloo' make='Holden' year='2006'>
                                                                           <country>Australia</country>
//Result
                                                                           <record type='speed'>
Peel                                                                      Production Pickup Truck with speed of 271kph
                                                                        </record>
// names of cars with records sorted by year                            </car>
                                                                        <car name='P50' make='Peel' year='1962'>
println records.car.list().sort{
                                                                           <country>Isle of Man</country>
  it.@year.toInteger()                                                     <record type='size'>
}.'@name'*.text()                                                         Smallest Street-Legal Car at 99cm wide and 59 kg in weight
//Result                                                                 </record>
                                                                        </car>
[Royale, P50, HSV Maloo]
                                                                        <car name='Royale' make='Bugatti' year='1931'>
                                                                           <country>France</country>
// names of countries with ‘s’ in the name                                 <record type='price'>
println records.'**'.grep{                                                Most Valuable Car at $15 million
                                                                        </record>
  it.@type =~ 's.*'
                                                                        </car>
}*.parent().country*.text()                                           </records>
//Result
[Australia, Isle of Man]
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_mstr
Process -> FREUDENBERG_DEMO
User ->
Date -> Fri Dec 25 17:37:55 EST 2009
MessageCount -> 0
UID -> uniqueId-0
XML Generation


•   Building XML using simple Java


•   StreamingMarkupBuilder - A builder class for creating XML markup
Java
//assuming we have a Writer created already
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>");

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

new StreamingMarkupBuilder().bind {
   root {                             writer.write("<root>");
     a ( a1:'one' ) {                   writer.write(“<a a1=‘one’>”);
                                          writer.write("<b>3 < 5</b>");
       b { mkp.yield( '3 < 5' ) }         writer.write("<c a2=‘two’>blah</c>");
       c ( a2:'two', 'blah' )             writer.write("<d>");
       d {                                  writer.write("<f>hello</f>");
          f (‘hello’)                     writer.write("</d>");
       }                                writer.write("</a>");
                                      writer.write("</root>");
     }
   }
}.toString()

//Result
<root>
   <a a1='one'>
     <b>3 &lt; 5</b>
     <c a2='two'>blah</c>
     <d>
        <f>hello</f>
     </d>
   </a>
</root>
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>
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>
EOs inside Groovy


•   Setup


•   Demo
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      Employee



    •
                      age                                        Job
        Manager       job        0..1*                         employees
                                 0..1*

    •
                      manager             Manager              name
        Job           name                employees            owner

                      salary              jobs        0..1 *

                                          name
DEMO
Questions
Bonus
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.
Reading configuration with ConfigSlurper
def config = new ConfigSlurper().parse (configFile)                def configFile = '''
//get the all of the config data                                       WOWODC {
println config.WOWODC                                                      Bonus {
                                                                                testId = 1
//Result
                                                                                testName = "Hello Bonus Test string"
["Bonus":["testId":1, "testName":"Hello Bonus Test string"],
 "BonusList":["key1":"val1", "hi":"hello"]]                                }

//get only the Bonus section                                                 BonusList {
println config.WOWODC.Bonus                                                      key1 = 'val1'
                                                                                 hi = 'hello'
//Result                                                                     }
["testId":1, "testName":"Hello Bonus Test string"]
                                                                         }
//get only the testId value                                        '''
println config.WOWODC.Bonus.testId

//Result
1

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

//Result
key1 = val1
hi = hello
Updating configuration with ConfigSlurper
//get the all of the config data              WOWODC {
config.Hi.GoodBuy.say = 'Hello'                          Bonus {
                                                             testId = 1
def sw = new StringWriter()                                  testName = "Hello Bonus Test string"
println config?.writeTo(sw).toString()                   }

//Result -->                                             BonusList {
WOWODC {                                                     key1 = 'val1'
	   Bonus {                                                  hi = 'hello'
	   	   testId=1                                         }
	   	   testName="Hello Bonus Test string"        }
	   }
	   BonusList {
	   	   key1="val1"
	   	   hi="hello"
	   }
}
Hi.GoodBuy.say="Hello" // got updated
Updating configuration with ConfigSlurper
//get the all of the config data                 WOWODC {
config.Hi.GoodBuy.tell = 'Hi'                    	   Bonus {
                                                 	   	   testId=1
def sw = new StringWriter()                      	   	   testName="Hello Bonus Test string"
println config?.writeTo(sw).toString()           	   }
                                                 	   BonusList {
//Result                                         	   	   key1="val1"
WOWODC {                                         	   	   hi="hello"
	   Bonus {                                      	   }
	   	   testId=1                                 }
	   	   testName="Hello Bonus Test string"       Hi.GoodBuy.say="Hello"
	   }
	   BonusList {
	   	   key1="val1"
	   	   hi="hello"
	   }
}
Hi {
	   GoodBuy {
	   	   say="Hello"
	   	   tell="Hi" // got updated
	   }
}
Updating configuration with ConfigSlurper
//get the all of the config data                 WOWODC {
config.WOWODC.Bonus.testId = 2                   	   Bonus {
                                                 	   	   testId=1
def sw = new StringWriter()                      	   	   testName="Hello Bonus Test string"
println config?.writeTo(sw).toString()           	   }
                                                 	   BonusList {
//Result -->                                     	   	   key1="val1"
WOWODC {                                         	   	   hi="hello"
	   Bonus {                                      	   }
	   	   testId=2 // got updated                  }
	   	   testName="Hello Bonus Test string"       Hi {
	   }                                            	   GoodBuy {
	   BonusList {                                  	   	   say="Hello"
	   	   key1="val1"                              	   	   tell="Hi"
	   	   hi="hello"                               	   }
	   }                                            }
}
Hi {
	   GoodBuy {
	   	   say="Hello"
	   	   tell="Hi"
	   }
}
DEMO

More Related Content

More from WO Community

In memory OLAP engine
In memory OLAP engineIn memory OLAP engine
In memory OLAP engineWO Community
 
Using Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsUsing Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsWO Community
 
Build and deployment
Build and deploymentBuild and deployment
Build and deploymentWO Community
 
Chaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldChaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldWO Community
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful ControllersWO Community
 
Deploying WO on Windows
Deploying WO on WindowsDeploying WO on Windows
Deploying WO on WindowsWO Community
 
Unit Testing with WOUnit
Unit Testing with WOUnitUnit Testing with WOUnit
Unit Testing with WOUnitWO Community
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO DevsWO Community
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache CayenneWO Community
 
iOS for ERREST - alternative version
iOS for ERREST - alternative versioniOS for ERREST - alternative version
iOS for ERREST - alternative versionWO Community
 
"Framework Principal" pattern
"Framework Principal" pattern"Framework Principal" pattern
"Framework Principal" patternWO Community
 
Localizing your apps for multibyte languages
Localizing your apps for multibyte languagesLocalizing your apps for multibyte languages
Localizing your apps for multibyte languagesWO Community
 
D2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRollerD2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRollerWO Community
 
CMS / BLOG and SnoWOman
CMS / BLOG and SnoWOmanCMS / BLOG and SnoWOman
CMS / BLOG and SnoWOmanWO Community
 

More from WO Community (20)

KAAccessControl
KAAccessControlKAAccessControl
KAAccessControl
 
In memory OLAP engine
In memory OLAP engineIn memory OLAP engine
In memory OLAP engine
 
Using Nagios to monitor your WO systems
Using Nagios to monitor your WO systemsUsing Nagios to monitor your WO systems
Using Nagios to monitor your WO systems
 
Build and deployment
Build and deploymentBuild and deployment
Build and deployment
 
High availability
High availabilityHigh availability
High availability
 
Chaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real WorldChaining the Beast - Testing Wonder Applications in the Real World
Chaining the Beast - Testing Wonder Applications in the Real World
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful Controllers
 
Deploying WO on Windows
Deploying WO on WindowsDeploying WO on Windows
Deploying WO on Windows
 
Unit Testing with WOUnit
Unit Testing with WOUnitUnit Testing with WOUnit
Unit Testing with WOUnit
 
Life outside WO
Life outside WOLife outside WO
Life outside WO
 
Apache Cayenne for WO Devs
Apache Cayenne for WO DevsApache Cayenne for WO Devs
Apache Cayenne for WO Devs
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache Cayenne
 
iOS for ERREST - alternative version
iOS for ERREST - alternative versioniOS for ERREST - alternative version
iOS for ERREST - alternative version
 
iOS for ERREST
iOS for ERRESTiOS for ERREST
iOS for ERREST
 
"Framework Principal" pattern
"Framework Principal" pattern"Framework Principal" pattern
"Framework Principal" pattern
 
Localizing your apps for multibyte languages
Localizing your apps for multibyte languagesLocalizing your apps for multibyte languages
Localizing your apps for multibyte languages
 
WOdka
WOdkaWOdka
WOdka
 
ERGroupware
ERGroupwareERGroupware
ERGroupware
 
D2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRollerD2W Branding Using jQuery ThemeRoller
D2W Branding Using jQuery ThemeRoller
 
CMS / BLOG and SnoWOman
CMS / BLOG and SnoWOmanCMS / BLOG and SnoWOman
CMS / BLOG and SnoWOman
 

Recently uploaded

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 

Recently uploaded (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 

Groovy XML Processing with WebObjects

  • 2. Outline • Java vs Groovy short cuts • XML parsing with Groovy • XML generating with Groovy • How to access EO inside Groovy
  • 3. 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
  • 4. 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
  • 5. Hello World! //JAVA class myfirstjavaprog { public static void main(String args[]) { System.out.println("Hello World!"); } } //GROOVY println "Hello World!" //GROOVY command line groovy -e "println 'Hello ' + args[0]" World! GROOVY SCRIPT ARG 1
  • 6. Method call on a Null Object //JAVA MyObject obj = null if (obj != null) { return obj.getChildren().getFirst() } else { return null } //GROOVY MyObject obj = null return obj?.getChildren()?.getFirst()
  • 7. 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) //RESULT 16 [ 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) //RESULT Name = John Address = Here Likes = WOWODC
  • 8. 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() //RESULT invoked hello directly println mine.foo("Mark", 19) //RESULT unknown method foo(Mark, 19)
  • 9. 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’ property println mine.greeting //RESULT read from property greeting //try to set ‘greeting’ property try { mine.greeting = 'hi' } catch(e) { println e.message } //RESULT wrote to property greeting //we can access a property directly using .@ syntax println mine.@greeting //RESULT accessed greeting directly
  • 10. 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 //RESULT Hi!!! //add new method ‘hello’ A.metaClass.hello = {-> "Hello!"} def a2 = new A() println a2.hello() //RESULT Hello!
  • 11. XML Parsing • XmlParser - supports GPath expressions for XML documents • XmlSlurper - lower overheads than XmlParser due to lazy evaluation
  • 12. 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> ''' }
  • 13. 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 == 3 def allRecords_s = records_s.car.size() assert allRecords_s == 3 def allNodes = records_p.depthFirst().size() assert allNodes_p == 10 def allNodes_s = records_s.depthFirst().collect{ it }.size() assert allNodes_s == 10 <records> <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> def firstRecord_p = records_p.car[0] <record type='speed'> def firstRecord_s = records_s.car[0] Production Pickup Truck with speed of 271kph </record> </car> assert 'car' == firstRecord_p.name() <car name='P50' make='Peel' year='1962'> <country>Isle of Man</country> assert 'car' == firstRecord_s.name() <record type='size'> Smallest Street-Legal Car at 99cm wide and 59 kg in weight assert 'Holden' == firstRecord_p.'@make' </record> </car> assert 'Holden' == firstRecord_s.@make.text() <car name='Royale' make='Bugatti' year='1931'> <country>France</country> assert 'Australia' == firstRecord_p.country.text() <record type='price'> Most Valuable Car at $15 million assert 'Australia' == firstRecord_s.country.text() </record> </car> </records>
  • 14. XmlParser vs XmlSlurper // 2 cars have an 'e' in the make assert records_p.car.findAll{ it.'@make'.contains('e') }.size() == 2 // option 1 assert records_s.car.findAll{ it.@make.text().contains('e') }.size() == 2 // option 2 assert 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>
  • 15. 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].country println countryOne.parent().@make.text() //Result Peel <records> println countryOne.'..'.@make.text() <car name='HSV Maloo' make='Holden' year='2006'> <country>Australia</country> //Result <record type='speed'> Peel Production Pickup Truck with speed of 271kph </record> // names of cars with records sorted by year </car> <car name='P50' make='Peel' year='1962'> println records.car.list().sort{ <country>Isle of Man</country> it.@year.toInteger() <record type='size'> }.'@name'*.text() Smallest Street-Legal Car at 99cm wide and 59 kg in weight //Result </record> </car> [Royale, P50, HSV Maloo] <car name='Royale' make='Bugatti' year='1931'> <country>France</country> // names of countries with ‘s’ in the name <record type='price'> println records.'**'.grep{ Most Valuable Car at $15 million </record> it.@type =~ 's.*' </car> }*.parent().country*.text() </records> //Result [Australia, Isle of Man]
  • 16. 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_mstr Process -> FREUDENBERG_DEMO User -> Date -> Fri Dec 25 17:37:55 EST 2009 MessageCount -> 0 UID -> uniqueId-0
  • 17. XML Generation • Building XML using simple Java • StreamingMarkupBuilder - A builder class for creating XML markup
  • 18. Java //assuming we have a Writer created already 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>"); //Result <root> <a a1='one'> <b>3 &lt; 5</b> <c a2='two'>blah</c> <d> <f>hello</f> </d> </a> </root>
  • 19. StreamingMarkupBuilder import groovy.xml.StreamingMarkupBuilder new StreamingMarkupBuilder().bind { root { writer.write("<root>"); a ( a1:'one' ) { writer.write(“<a a1=‘one’>”); writer.write("<b>3 < 5</b>"); b { mkp.yield( '3 < 5' ) } writer.write("<c a2=‘two’>blah</c>"); c ( a2:'two', 'blah' ) writer.write("<d>"); d { writer.write("<f>hello</f>"); f (‘hello’) writer.write("</d>"); } writer.write("</a>"); writer.write("</root>"); } } }.toString() //Result <root> <a a1='one'> <b>3 &lt; 5</b> <c a2='two'>blah</c> <d> <f>hello</f> </d> </a> </root>
  • 20. 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>
  • 21. 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>
  • 22. EOs inside Groovy • Setup • Demo
  • 23. 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 Employee • age Job Manager job 0..1* employees 0..1* • manager Manager name Job name employees owner salary jobs 0..1 * name
  • 24. DEMO
  • 26. Bonus
  • 27. 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.
  • 28. Reading configuration with ConfigSlurper def config = new ConfigSlurper().parse (configFile) def configFile = ''' //get the all of the config data WOWODC { println config.WOWODC Bonus { testId = 1 //Result testName = "Hello Bonus Test string" ["Bonus":["testId":1, "testName":"Hello Bonus Test string"], "BonusList":["key1":"val1", "hi":"hello"]] } //get only the Bonus section BonusList { println config.WOWODC.Bonus key1 = 'val1' hi = 'hello' //Result } ["testId":1, "testName":"Hello Bonus Test string"] } //get only the testId value ''' println config.WOWODC.Bonus.testId //Result 1 //list keys and values under BonusList section config.WOWODC.BonusList.each {println "${it.key} = ${it.value}"} //Result key1 = val1 hi = hello
  • 29. Updating configuration with ConfigSlurper //get the all of the config data WOWODC { config.Hi.GoodBuy.say = 'Hello' Bonus { testId = 1 def sw = new StringWriter() testName = "Hello Bonus Test string" println config?.writeTo(sw).toString() } //Result --> BonusList { WOWODC { key1 = 'val1' Bonus { hi = 'hello' testId=1 } testName="Hello Bonus Test string" } } BonusList { key1="val1" hi="hello" } } Hi.GoodBuy.say="Hello" // got updated
  • 30. Updating configuration with ConfigSlurper //get the all of the config data WOWODC { config.Hi.GoodBuy.tell = 'Hi' Bonus { testId=1 def sw = new StringWriter() testName="Hello Bonus Test string" println config?.writeTo(sw).toString() } BonusList { //Result key1="val1" WOWODC { hi="hello" Bonus { } testId=1 } testName="Hello Bonus Test string" Hi.GoodBuy.say="Hello" } BonusList { key1="val1" hi="hello" } } Hi { GoodBuy { say="Hello" tell="Hi" // got updated } }
  • 31. Updating configuration with ConfigSlurper //get the all of the config data WOWODC { config.WOWODC.Bonus.testId = 2 Bonus { testId=1 def sw = new StringWriter() testName="Hello Bonus Test string" println config?.writeTo(sw).toString() } BonusList { //Result --> key1="val1" WOWODC { hi="hello" Bonus { } testId=2 // got updated } testName="Hello Bonus Test string" Hi { } GoodBuy { BonusList { say="Hello" key1="val1" tell="Hi" hi="hello" } } } } Hi { GoodBuy { say="Hello" tell="Hi" } }
  • 32. DEMO