SlideShare a Scribd company logo
Scripting GeoServer with GeoScript Justin Deoliveira and Tim Schaub
GeoScript? Spatial capabilities for scripting languages Groovy JavaScript Python Scala Higher level api for GeoTools Convenient, concise, complete Make easy things easy Faster development turnaround No recompilation/rebuilding
GeoScript
GeoScript
GeoScript ... import org.geotools.data.DataStore; import org.geotools.data.postgis.PostgisNGDataStoreFactory; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.jdbc.JDBCDataStoreFactory; import org.opengis.feature.Feature; ... Map<String,Serializable> params = new HashMap<String, Serializable>(); params.put(JDBCDataStoreFactory.HOST.key, &quot;localhost&quot;); params.put(JDBCDataStoreFactory.PORT.key, 5432); params.put(JDBCDataStoreFactory.DATABASE.key, &quot;geoscript&quot;); params.put(JDBCDataStoreFactory.DBTYPE.key, &quot;postgis&quot;); params.put(JDBCDataStoreFactory.USER.key, &quot;jdeolive&quot;); PostgisNGDataStoreFactory factory = new PostgisNGDataStoreFactory(); DataStore pg = factory.createDataStore(params);  FeatureCollection features = pg.getFeatureSource(&quot;states&quot;).getFeatures(); FeatureIterator it = features.features(); try {    while(it.hasNext()) {       Feature f = it.next();       System.out.println(f.getProperty(&quot;STATE_NAME&quot;).getValue());    } } finally {    it.close(); } Java
GeoScript from geoscript.workspace import PostGIS pg = PostGIS('geoscript') for f in pg['states'].features():    print f['STATE_NAME'] Python JavaScript var PostGIS = require(&quot;geoscript/workspace&quot;).PostGIS; var pg = PostGIS(&quot;geoscript&quot;); pg.get(&quot;states&quot;).features.forEach(function(f) {      print(f.get(&quot;STATE_NAME&quot;)); });
GeoServer
GeoServer
Script Hooks - Data Formats Data Formats Drivers for spatial formats Map to internal data model
Script Hooks - Data Formats from geoserver import datastore from geoscript.layer import readJSON class GeoJSON(object):    @datastore('GeoJSON', 'GeoJSON', file=('GeoJSON file', str))    def __init__(self, file):      self.json = readJSON(file)    def layers(self):      return [self.json.name]    def get(self, layer):      return self.json GeoJSON DataStore
Script Hooks - Data Formats from geoserver import datastore from geoscript.layer import readJSON class GeoJSON(object):    @datastore('GeoJSON', 'GeoJSON', file=('GeoJSON file', str))    def __init__(self, file):      self.json = readJSON(file)    def layers(self):      return [self.json.name]    def get(self, layer):      return self.json GeoJSON DataStore
Script Hooks - Output Formats Output Formats Drivers for exchange formats Map from internal data model
Script Hooks - Output Formats from geoserver.format import vector_format @vector_format('property', 'text/plain') def write(data, out):   for f in data.features:     values = [str(val) for val in f.values()]     out.write('%s=%s\n' % (f.id, '|'.join(values)) Property File Format states.1=MULTIPOLYGON (((37.51 -88.07, ... 37.51 -88.07)))|Illinois states.2=MULTIPOLYGON (((38.97 -77.00, ... 38.97 -77.01)))|District of Columbia states.3=MULTIPOLYGON (((38.56 -75.71, ... 38.56 -75.71)))|Delaware states.4=MULTIPOLYGON (((38.48 -79.23, ... 38.48 -79.23)))|West Virginia    .    .    . .../wfs?request=GetFeature&typename=topp:states&outputformat=property
Script Hooks - Process Processes Smarts of WPS Simplicity of scripting
Script Hooks - Process var Process = require(&quot;geoscript/process&quot;).Process; exports.process = new Process({      title: &quot;JavaScript Buffer Process&quot;,      description: &quot;Process that buffers a geometry.&quot;,      inputs: {          geom: {              type: &quot;Geometry&quot;,              title: &quot;Input Geometry&quot;          },          distance: {              type: &quot;Double&quot;,              title: &quot;Buffer Distance&quot;          }      },      outputs: {          result: {              type: &quot;Geometry&quot;,              title: &quot;Result&quot;          }      },      run: function(inputs) {          return {result: inputs.geom.buffer(inputs.distance)};      } }); JavaScript
Script Hooks - Filter Functions Filter Functions Filtering for WFS and WMS Callable via SLD from geosever.filter import function from geoscript.geom import Polygon @function def areaGreaterThan(feature, area):    return feature.geom.area > area Area Function
Script Hooks - Transactions Intercept WFS transactions with a wfs.js script in your data directory. exports.beforeCommit = function(details, request) {      LOGGER.info(&quot;beforeCommit&quot;);      var records = details[&quot;PreInsert&quot;] || [];           records.forEach(function(record) {          var feature = record.feature;          feature.geometry = feature.geometry.simplify(10);      }); }; JavaScript
Script Hooks - Web/HTTP &quot;apps&quot; Simple WGSI-like environment Access to catalog/data def app(environ, start_response):     start_response('200 OK', [('Content-type','text/plain')])     return 'Hello world!' Hello World App
Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
Data Summary App Demo
Fusion Tables DataStore class GFT(object):    @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))     def __init__(self, user, passwd):      token = ClientLogin().authorize(user, passwd)      self.ft = ftclient.ClientLoginFTClient(token)    def layers(self):      return [tbl.name for tbl in self.tables()]           def get(self, layer):      try:        return Layer(filter(lambda t: t.name == layer, self.tables())[0])      except IndexError:        raise Exception('No table named %s' % layer)    def tables(self):      tables = self.ft.query(SQL().showTables())      return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
Fusion Tables DataStore class GFT(object):    @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))     def __init__(self, user, passwd):      token = ClientLogin().authorize(user, passwd)      self.ft = ftclient.ClientLoginFTClient(token)    def layers(self):      return [tbl.name for tbl in self.tables()]           def get(self, layer):      try:        return Layer(filter(lambda t: t.name == layer, self.tables())[0])      except IndexError:        raise Exception('No table named %s' % layer)    def tables(self):      tables = self.ft.query(SQL().showTables())      return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
Fusion Tables DataStore class GFT(object):    @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))     def __init__(self, user, passwd):      token = ClientLogin().authorize(user, passwd)      self.ft = ftclient.ClientLoginFTClient(token)    def layers(self):      return [tbl.name for tbl in self.tables()]           def get(self, layer):      try:        return Layer(filter(lambda t: t.name == layer, self.tables())[0])      except IndexError:        raise Exception('No table named %s' % layer)    def tables(self):      tables = self.ft.query(SQL().showTables())      return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
Fusion Tables DataStore class GFT(object):    @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))     def __init__(self, user, passwd):      token = ClientLogin().authorize(user, passwd)      self.ft = ftclient.ClientLoginFTClient(token)    def layers(self):      return [tbl.name for tbl in self.tables()]           def get(self, layer):      try:        return Layer(filter(lambda t: t.name == layer, self.tables())[0])      except IndexError:        raise Exception('No table named %s' % layer)    def tables(self):      tables = self.ft.query(SQL().showTables())      return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]]) for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]])          for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]])          for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
Fusion Tables DataStore class Layer(object):     ...     def features(self):       rows = self.tbl.gft.ft.query(SQL().select(self.tbl.id))       rows = rows.split('\n')[1:-1]       for row in rows:         vals = csv.reader([row]).next()         atts = []         for i in range(0, len(vals)):           val = vals[i]           fld = self.schema.get(i)           if issubclass(fld.typ, Geometry):             val = readKML(val)           atts.append(val)          yield Feature(atts, schema=self.schema)
Fusion Tables DataStore Demo
H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
H2 Output Format Demo
Scripted WPS and  WFS Transaction Hooks Demo
Thanks! http://geoscript.org http://geoserver.org Questions?

More Related Content

PPT
The State of GeoServer
PPT
GeoScript - Spatial Capabilities for Scripting Languages
PDF
Scripting GeoServer
PDF
Utilizing Powerful Extensions for Analytics and Operations
PDF
The Ring programming language version 1.5.2 book - Part 44 of 181
PDF
Map kit light
PPTX
Build Lightweight Web Module
PDF
RubyKaigi2015 making robots-with-mruby
The State of GeoServer
GeoScript - Spatial Capabilities for Scripting Languages
Scripting GeoServer
Utilizing Powerful Extensions for Analytics and Operations
The Ring programming language version 1.5.2 book - Part 44 of 181
Map kit light
Build Lightweight Web Module
RubyKaigi2015 making robots-with-mruby

What's hot (20)

PDF
Relaxing With CouchDB
PDF
Letswift19-clean-architecture
PDF
InterConnect: Java, Node.js and Swift - Which, Why and When
PDF
The Ring programming language version 1.5.3 book - Part 40 of 184
PDF
HTTP APIs as first class procedures in your language: cutting out SDK complex...
TXT
c++ project on restaurant billing
PPTX
ql.io at NodePDX
TXT
Railwaynew
PDF
Reactive, component 그리고 angular2
PPT
Python And GIS - Beyond Modelbuilder And Pythonwin
PDF
Minimizing Decision Fatigue to Improve Team Productivity
PDF
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
PDF
Interactive Session on Sparkling Water
PPTX
MongoDB Analytics: Learn Aggregation by Example - Exploratory Analytics and V...
DOCX
Cs pritical file
TXT
c++ program for Railway reservation
PDF
JavaScript 2016 for C# Developers
DOCX
Tugas praktikukm pemrograman c++
PDF
High Performance tDiary
Relaxing With CouchDB
Letswift19-clean-architecture
InterConnect: Java, Node.js and Swift - Which, Why and When
The Ring programming language version 1.5.3 book - Part 40 of 184
HTTP APIs as first class procedures in your language: cutting out SDK complex...
c++ project on restaurant billing
ql.io at NodePDX
Railwaynew
Reactive, component 그리고 angular2
Python And GIS - Beyond Modelbuilder And Pythonwin
Minimizing Decision Fatigue to Improve Team Productivity
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
Interactive Session on Sparkling Water
MongoDB Analytics: Learn Aggregation by Example - Exploratory Analytics and V...
Cs pritical file
c++ program for Railway reservation
JavaScript 2016 for C# Developers
Tugas praktikukm pemrograman c++
High Performance tDiary
Ad

Similar to Scripting GeoServer with GeoScript (20)

PPT
Introduction To Groovy 2005
ODP
Use of django at jolt online v3
PDF
Functional programming using underscorejs
PPT
OWB11gR2 - Extending ETL
PDF
Cross Domain Web
Mashups with JQuery and Google App Engine
PPT
What's New in ZF 1.10
PPT
Plone For Developers - World Plone Day, 2009
PPT
Groovy Introduction - JAX Germany - 2008
PPT
Boston Computing Review - Java Server Pages
PPT
I Feel Pretty
PPTX
AWS Hadoop and PIG and overview
PPT
Going crazy with Node.JS and CakePHP
PPT
JavaScript on Rails 튜토리얼
PPTX
Jackson beyond JSON: XML, CSV
PPTX
Introduction to Apache Pig
ODP
Non Conventional Android Programming En
ODP
Non Conventional Android Programming (English)
PDF
Demoiselle Spatial Latinoware 2011
ODP
Intro To PostGIS
PPT
Html and i_phone_mobile-2
Introduction To Groovy 2005
Use of django at jolt online v3
Functional programming using underscorejs
OWB11gR2 - Extending ETL
Cross Domain Web
Mashups with JQuery and Google App Engine
What's New in ZF 1.10
Plone For Developers - World Plone Day, 2009
Groovy Introduction - JAX Germany - 2008
Boston Computing Review - Java Server Pages
I Feel Pretty
AWS Hadoop and PIG and overview
Going crazy with Node.JS and CakePHP
JavaScript on Rails 튜토리얼
Jackson beyond JSON: XML, CSV
Introduction to Apache Pig
Non Conventional Android Programming En
Non Conventional Android Programming (English)
Demoiselle Spatial Latinoware 2011
Intro To PostGIS
Html and i_phone_mobile-2
Ad

Recently uploaded (20)

PDF
Encapsulation theory and applications.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
cuic standard and advanced reporting.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Approach and Philosophy of On baking technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Spectroscopy.pptx food analysis technology
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Encapsulation theory and applications.pdf
Review of recent advances in non-invasive hemoglobin estimation
cuic standard and advanced reporting.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Programs and apps: productivity, graphics, security and other tools
Unlocking AI with Model Context Protocol (MCP)
Chapter 3 Spatial Domain Image Processing.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Understanding_Digital_Forensics_Presentation.pptx
Big Data Technologies - Introduction.pptx
MIND Revenue Release Quarter 2 2025 Press Release
20250228 LYD VKU AI Blended-Learning.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Approach and Philosophy of On baking technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Spectroscopy.pptx food analysis technology
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx

Scripting GeoServer with GeoScript

  • 1. Scripting GeoServer with GeoScript Justin Deoliveira and Tim Schaub
  • 2. GeoScript? Spatial capabilities for scripting languages Groovy JavaScript Python Scala Higher level api for GeoTools Convenient, concise, complete Make easy things easy Faster development turnaround No recompilation/rebuilding
  • 5. GeoScript ... import org.geotools.data.DataStore; import org.geotools.data.postgis.PostgisNGDataStoreFactory; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.jdbc.JDBCDataStoreFactory; import org.opengis.feature.Feature; ... Map<String,Serializable> params = new HashMap<String, Serializable>(); params.put(JDBCDataStoreFactory.HOST.key, &quot;localhost&quot;); params.put(JDBCDataStoreFactory.PORT.key, 5432); params.put(JDBCDataStoreFactory.DATABASE.key, &quot;geoscript&quot;); params.put(JDBCDataStoreFactory.DBTYPE.key, &quot;postgis&quot;); params.put(JDBCDataStoreFactory.USER.key, &quot;jdeolive&quot;); PostgisNGDataStoreFactory factory = new PostgisNGDataStoreFactory(); DataStore pg = factory.createDataStore(params);  FeatureCollection features = pg.getFeatureSource(&quot;states&quot;).getFeatures(); FeatureIterator it = features.features(); try {   while(it.hasNext()) {       Feature f = it.next();       System.out.println(f.getProperty(&quot;STATE_NAME&quot;).getValue());   } } finally {   it.close(); } Java
  • 6. GeoScript from geoscript.workspace import PostGIS pg = PostGIS('geoscript') for f in pg['states'].features():   print f['STATE_NAME'] Python JavaScript var PostGIS = require(&quot;geoscript/workspace&quot;).PostGIS; var pg = PostGIS(&quot;geoscript&quot;); pg.get(&quot;states&quot;).features.forEach(function(f) {     print(f.get(&quot;STATE_NAME&quot;)); });
  • 9. Script Hooks - Data Formats Data Formats Drivers for spatial formats Map to internal data model
  • 10. Script Hooks - Data Formats from geoserver import datastore from geoscript.layer import readJSON class GeoJSON(object):   @datastore('GeoJSON', 'GeoJSON', file=('GeoJSON file', str))   def __init__(self, file):     self.json = readJSON(file)   def layers(self):     return [self.json.name]   def get(self, layer):     return self.json GeoJSON DataStore
  • 11. Script Hooks - Data Formats from geoserver import datastore from geoscript.layer import readJSON class GeoJSON(object):   @datastore('GeoJSON', 'GeoJSON', file=('GeoJSON file', str))   def __init__(self, file):     self.json = readJSON(file)   def layers(self):     return [self.json.name]   def get(self, layer):     return self.json GeoJSON DataStore
  • 12. Script Hooks - Output Formats Output Formats Drivers for exchange formats Map from internal data model
  • 13. Script Hooks - Output Formats from geoserver.format import vector_format @vector_format('property', 'text/plain') def write(data, out):   for f in data.features:     values = [str(val) for val in f.values()]     out.write('%s=%s\n' % (f.id, '|'.join(values)) Property File Format states.1=MULTIPOLYGON (((37.51 -88.07, ... 37.51 -88.07)))|Illinois states.2=MULTIPOLYGON (((38.97 -77.00, ... 38.97 -77.01)))|District of Columbia states.3=MULTIPOLYGON (((38.56 -75.71, ... 38.56 -75.71)))|Delaware states.4=MULTIPOLYGON (((38.48 -79.23, ... 38.48 -79.23)))|West Virginia   .   .   . .../wfs?request=GetFeature&typename=topp:states&outputformat=property
  • 14. Script Hooks - Process Processes Smarts of WPS Simplicity of scripting
  • 15. Script Hooks - Process var Process = require(&quot;geoscript/process&quot;).Process; exports.process = new Process({     title: &quot;JavaScript Buffer Process&quot;,     description: &quot;Process that buffers a geometry.&quot;,     inputs: {         geom: {             type: &quot;Geometry&quot;,             title: &quot;Input Geometry&quot;         },         distance: {             type: &quot;Double&quot;,             title: &quot;Buffer Distance&quot;         }     },     outputs: {         result: {             type: &quot;Geometry&quot;,             title: &quot;Result&quot;         }     },     run: function(inputs) {         return {result: inputs.geom.buffer(inputs.distance)};     } }); JavaScript
  • 16. Script Hooks - Filter Functions Filter Functions Filtering for WFS and WMS Callable via SLD from geosever.filter import function from geoscript.geom import Polygon @function def areaGreaterThan(feature, area):   return feature.geom.area > area Area Function
  • 17. Script Hooks - Transactions Intercept WFS transactions with a wfs.js script in your data directory. exports.beforeCommit = function(details, request) {     LOGGER.info(&quot;beforeCommit&quot;);     var records = details[&quot;PreInsert&quot;] || [];          records.forEach(function(record) {         var feature = record.feature;         feature.geometry = feature.geometry.simplify(10);     }); }; JavaScript
  • 18. Script Hooks - Web/HTTP &quot;apps&quot; Simple WGSI-like environment Access to catalog/data def app(environ, start_response):    start_response('200 OK', [('Content-type','text/plain')])    return 'Hello world!' Hello World App
  • 19. Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
  • 20. Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
  • 21. Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
  • 22. Data Summary App from geoserver.catalog import Layer from StringIO import StringIO def app(env, start_response):   kvp = dict([tuple(kv.split('=')) for kv in env['QUERY_STRING'].split('&')])   layer = kvp['layer']   l = Layer(layer, store=None)   buf = StringIO()   buf.write('Layer: %s\n' % l.name)   data = l.data   buf.write(' Format: %s\n' % data.format)   buf.write(' Feature count: %d\n' % data.count())   buf.write(' CRS/Projection: %s\n' % data.proj.wkt)   b = data.bounds()   buf.write(' Bounds: (%f,%f,%f,%f)\n' % (b.west, b.south, b.east, b.north))   buf.write(' Fields:\n')   buf.write('\n'.join(['   %s' % repr(fld) for fld in data.schema.fields]))   buf.write('\n')   start_response('200 OK', [('Content-type','text/plain')])   return buf.getvalue()
  • 24. Fusion Tables DataStore class GFT(object):   @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))    def __init__(self, user, passwd):     token = ClientLogin().authorize(user, passwd)     self.ft = ftclient.ClientLoginFTClient(token)   def layers(self):     return [tbl.name for tbl in self.tables()]          def get(self, layer):     try:       return Layer(filter(lambda t: t.name == layer, self.tables())[0])     except IndexError:       raise Exception('No table named %s' % layer)   def tables(self):     tables = self.ft.query(SQL().showTables())     return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
  • 25. Fusion Tables DataStore class GFT(object):   @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))    def __init__(self, user, passwd):     token = ClientLogin().authorize(user, passwd)     self.ft = ftclient.ClientLoginFTClient(token)   def layers(self):     return [tbl.name for tbl in self.tables()]          def get(self, layer):     try:       return Layer(filter(lambda t: t.name == layer, self.tables())[0])     except IndexError:       raise Exception('No table named %s' % layer)   def tables(self):     tables = self.ft.query(SQL().showTables())     return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
  • 26. Fusion Tables DataStore class GFT(object):   @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))    def __init__(self, user, passwd):     token = ClientLogin().authorize(user, passwd)     self.ft = ftclient.ClientLoginFTClient(token)   def layers(self):     return [tbl.name for tbl in self.tables()]          def get(self, layer):     try:       return Layer(filter(lambda t: t.name == layer, self.tables())[0])     except IndexError:       raise Exception('No table named %s' % layer)   def tables(self):     tables = self.ft.query(SQL().showTables())     return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
  • 27. Fusion Tables DataStore class GFT(object):   @datastore('GFT', 'Google Fusion Tables',                user=('User email', str), passwd=('Password', str))    def __init__(self, user, passwd):     token = ClientLogin().authorize(user, passwd)     self.ft = ftclient.ClientLoginFTClient(token)   def layers(self):     return [tbl.name for tbl in self.tables()]          def get(self, layer):     try:       return Layer(filter(lambda t: t.name == layer, self.tables())[0])     except IndexError:       raise Exception('No table named %s' % layer)   def tables(self):     tables = self.ft.query(SQL().showTables())     return [Table(self,*row.split(',')) for row in tables.split('\n')[1:-1]]
  • 28. Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]]) for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
  • 29. Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]])          for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
  • 30. Fusion Tables DataStore __types = {'string':str, 'number': float, 'location':Geometry} class Layer(object):     def __init__(self, tbl):       self.tbl = tbl       self.name = tbl.name       self.workspace = tbl.gft       self.proj = Projection('epsg:4326')       self.schema = Schema(tbl.name, [(col[0], __types[col[1]])          for col in tbl.schema()])     def bounds(self):       return reduce(lambda x,y: x.expand(y.bounds), self.features(), Bounds())     def features(self):       ...
  • 31. Fusion Tables DataStore class Layer(object):     ...     def features(self):       rows = self.tbl.gft.ft.query(SQL().select(self.tbl.id))       rows = rows.split('\n')[1:-1]       for row in rows:         vals = csv.reader([row]).next()         atts = []         for i in range(0, len(vals)):           val = vals[i]           fld = self.schema.get(i)           if issubclass(fld.typ, Geometry):             val = readKML(val)           atts.append(val)          yield Feature(atts, schema=self.schema)
  • 33. H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
  • 34. H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
  • 35. H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
  • 36. H2 Output Format @vector_format('h2', 'application/zip') def write(data, out):   dir = tempfile.mkdtemp()   # create the database and copy the features into it   db = H2(data.schema.name, dir=dir)   layer = db.create(schema=data.schema)   for f in data.features:     layer.add(f)   db.close()   # zip and ship   file = tempfile.mktemp()   zip = zipfile.ZipFile(file, 'w')   for root, dirs, files in os.walk(dir):     name = abspath(root)[len(abspath(dir)):]       for f in files:       zip.write(join(root,f), join(name,f), zipfile.ZIP_DEFLATED)   zip.close()   shutil.copyfileobj(open(file, 'r'), out)   # clean up   os.remove(file)   shutil.rmtree(dir)
  • 38. Scripted WPS and  WFS Transaction Hooks Demo