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

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 

Recently uploaded (20)

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 

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