From acc732b8c0d8aacd438946be2c4b67d342db9ca3 Mon Sep 17 00:00:00 2001 From: David Turanski Date: Wed, 25 Oct 2017 18:00:11 -0400 Subject: [PATCH] Add Gemfire Samples and Migrate to Spring Cloud Dataflow Doc Framework --- .gitignore | 1 + README.adoc | 38 +- .../celsius-converter-processor/README.adoc | 172 ----- pom.xml | 315 ++++++++++ src/main/asciidoc/Guardfile | 20 + .../analytics/twitter-analytics/main.adoc | 101 ++- src/main/asciidoc/cloudfoundry-server.adoc | 66 ++ src/main/asciidoc/coalesce.rb | 62 ++ .../datascience/species-prediction/main.adoc | 65 +- src/main/asciidoc/docinfo.html | 76 +++ .../main/asciidoc/functions/main.adoc | 78 +-- src/main/asciidoc/geode-setup.adoc | 13 + src/main/asciidoc/images/scdf-dashboard.png | Bin 0 -> 112258 bytes .../asciidoc}/images/twitter_analytics.png | Bin src/main/asciidoc/index-docinfo.xml | 27 + src/main/asciidoc/index.adoc | 35 ++ src/main/asciidoc/local-server.adoc | 9 + src/main/asciidoc/maven-access.adoc | 7 + src/main/asciidoc/overview.adoc | 23 + src/main/asciidoc/shell.adoc | 30 + .../cassandra/http-to-cassandra/local.adoc | 78 +++ .../cassandra/http-to-cassandra/main.adoc | 25 + .../cassandra/http-to-cassandra/pcf.adoc | 99 +++ .../celsius-converter-processor/main.adoc | 161 +++++ .../gemfire/gemfire-cq-log/local.adoc | 91 +++ .../gemfire/gemfire-cq-log/main.adoc | 31 + .../streaming/gemfire/gemfire-cq-log/pcf.adoc | 114 ++++ .../streaming/gemfire/gemfire-log/local.adoc | 106 ++++ .../streaming/gemfire/gemfire-log/main.adoc | 30 + .../streaming/gemfire/gemfire-log/pcf.adoc | 110 ++++ .../streaming/gemfire/http-gemfire/local.adoc | 78 +++ .../streaming/gemfire/http-gemfire/main.adoc | 29 + .../streaming/gemfire/http-gemfire/pcf.adoc | 106 ++++ .../streaming/jdbc/http-mysql/local.adoc | 74 +++ .../streaming/jdbc/http-mysql/main.adoc | 25 + .../streaming/jdbc/http-mysql/pcf.adoc | 104 +++ .../batch-job-1.3.0.BUILD-SNAPSHOT.jar | Bin .../asciidoc/tasks/simple-batch-job/main.adoc | 125 +--- src/main/docbook/css/highlight.css | 35 ++ src/main/docbook/css/manual-multipage.css | 9 + src/main/docbook/css/manual-singlepage.css | 6 + src/main/docbook/css/manual.css | 348 +++++++++++ src/main/docbook/images/background.png | Bin 0 -> 10947 bytes src/main/docbook/images/caution.png | Bin 0 -> 2099 bytes src/main/docbook/images/cover.png | Bin 0 -> 78214 bytes src/main/docbook/images/important.png | Bin 0 -> 2085 bytes src/main/docbook/images/logo.png | Bin 0 -> 19499 bytes src/main/docbook/images/logo.svg | 16 + src/main/docbook/images/note.png | Bin 0 -> 2257 bytes src/main/docbook/images/tip.png | Bin 0 -> 931 bytes src/main/docbook/images/warning.png | Bin 0 -> 2130 bytes src/main/docbook/xsl/common.xsl | 45 ++ src/main/docbook/xsl/epub.xsl | 31 + src/main/docbook/xsl/html-multipage.xsl | 73 +++ src/main/docbook/xsl/html-singlepage.xsl | 30 + src/main/docbook/xsl/html.xsl | 141 +++++ src/main/docbook/xsl/pdf.xsl | 591 ++++++++++++++++++ src/main/docbook/xsl/xslthl-config.xml | 23 + src/main/docbook/xsl/xslthl/asciidoc-hl.xml | 41 ++ src/main/docbook/xsl/xslthl/bourne-hl.xml | 95 +++ src/main/docbook/xsl/xslthl/c-hl.xml | 117 ++++ src/main/docbook/xsl/xslthl/cpp-hl.xml | 151 +++++ src/main/docbook/xsl/xslthl/csharp-hl.xml | 194 ++++++ src/main/docbook/xsl/xslthl/css-hl.xml | 176 ++++++ src/main/docbook/xsl/xslthl/html-hl.xml | 122 ++++ src/main/docbook/xsl/xslthl/ini-hl.xml | 45 ++ src/main/docbook/xsl/xslthl/java-hl.xml | 117 ++++ src/main/docbook/xsl/xslthl/javascript-hl.xml | 147 +++++ src/main/docbook/xsl/xslthl/json-hl.xml | 37 ++ src/main/docbook/xsl/xslthl/perl-hl.xml | 120 ++++ src/main/docbook/xsl/xslthl/php-hl.xml | 154 +++++ src/main/docbook/xsl/xslthl/properties-hl.xml | 38 ++ src/main/docbook/xsl/xslthl/python-hl.xml | 100 +++ src/main/docbook/xsl/xslthl/ruby-hl.xml | 109 ++++ src/main/docbook/xsl/xslthl/sql2003-hl.xml | 565 +++++++++++++++++ src/main/docbook/xsl/xslthl/yaml-hl.xml | 47 ++ streaming/http-to-cassandra/README.adoc | 295 --------- streaming/http-to-mysql/README.adoc | 297 --------- 78 files changed, 5783 insertions(+), 1056 deletions(-) delete mode 100644 custom-apps/celsius-converter-processor/README.adoc create mode 100644 pom.xml create mode 100644 src/main/asciidoc/Guardfile rename analytics/twitter-analytics/README.adoc => src/main/asciidoc/analytics/twitter-analytics/main.adoc (70%) create mode 100644 src/main/asciidoc/cloudfoundry-server.adoc create mode 100644 src/main/asciidoc/coalesce.rb rename datascience/species-prediction/README.adoc => src/main/asciidoc/datascience/species-prediction/main.adoc (74%) create mode 100644 src/main/asciidoc/docinfo.html rename functions/README.adoc => src/main/asciidoc/functions/main.adoc (83%) create mode 100644 src/main/asciidoc/geode-setup.adoc create mode 100644 src/main/asciidoc/images/scdf-dashboard.png rename {analytics/twitter-analytics => src/main/asciidoc}/images/twitter_analytics.png (100%) create mode 100644 src/main/asciidoc/index-docinfo.xml create mode 100644 src/main/asciidoc/index.adoc create mode 100644 src/main/asciidoc/local-server.adoc create mode 100644 src/main/asciidoc/maven-access.adoc create mode 100644 src/main/asciidoc/overview.adoc create mode 100644 src/main/asciidoc/shell.adoc create mode 100644 src/main/asciidoc/streaming/cassandra/http-to-cassandra/local.adoc create mode 100644 src/main/asciidoc/streaming/cassandra/http-to-cassandra/main.adoc create mode 100644 src/main/asciidoc/streaming/cassandra/http-to-cassandra/pcf.adoc create mode 100644 src/main/asciidoc/streaming/custom-apps/celsius-converter-processor/main.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-cq-log/local.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-cq-log/main.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-cq-log/pcf.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-log/local.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-log/main.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/gemfire-log/pcf.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/http-gemfire/local.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/http-gemfire/main.adoc create mode 100644 src/main/asciidoc/streaming/gemfire/http-gemfire/pcf.adoc create mode 100644 src/main/asciidoc/streaming/jdbc/http-mysql/local.adoc create mode 100644 src/main/asciidoc/streaming/jdbc/http-mysql/main.adoc create mode 100644 src/main/asciidoc/streaming/jdbc/http-mysql/pcf.adoc rename {tasks => src/main/asciidoc/tasks}/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar (100%) rename tasks/simple-batch-job/README.adoc => src/main/asciidoc/tasks/simple-batch-job/main.adoc (72%) create mode 100644 src/main/docbook/css/highlight.css create mode 100644 src/main/docbook/css/manual-multipage.css create mode 100644 src/main/docbook/css/manual-singlepage.css create mode 100644 src/main/docbook/css/manual.css create mode 100644 src/main/docbook/images/background.png create mode 100644 src/main/docbook/images/caution.png create mode 100644 src/main/docbook/images/cover.png create mode 100644 src/main/docbook/images/important.png create mode 100644 src/main/docbook/images/logo.png create mode 100644 src/main/docbook/images/logo.svg create mode 100644 src/main/docbook/images/note.png create mode 100644 src/main/docbook/images/tip.png create mode 100644 src/main/docbook/images/warning.png create mode 100644 src/main/docbook/xsl/common.xsl create mode 100644 src/main/docbook/xsl/epub.xsl create mode 100644 src/main/docbook/xsl/html-multipage.xsl create mode 100644 src/main/docbook/xsl/html-singlepage.xsl create mode 100644 src/main/docbook/xsl/html.xsl create mode 100644 src/main/docbook/xsl/pdf.xsl create mode 100644 src/main/docbook/xsl/xslthl-config.xml create mode 100644 src/main/docbook/xsl/xslthl/asciidoc-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/bourne-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/c-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/cpp-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/csharp-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/css-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/html-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/ini-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/java-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/javascript-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/json-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/perl-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/php-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/properties-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/python-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/ruby-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/sql2003-hl.xml create mode 100644 src/main/docbook/xsl/xslthl/yaml-hl.xml delete mode 100644 streaming/http-to-cassandra/README.adoc delete mode 100644 streaming/http-to-mysql/README.adoc diff --git a/.gitignore b/.gitignore index e43b0f9..f2564bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +target/ diff --git a/README.adoc b/README.adoc index ddab21a..ce233ee 100644 --- a/README.adoc +++ b/README.adoc @@ -1,37 +1,9 @@ # Spring Cloud Data Flow Samples -This repository provides sample starter applications and code for use with the Spring Cloud Data Flow project. The following samples are available: +This repository provides various developer tutorials and samples for building data pipelines with Spring Cloud Data Flow. The samples are included in a document available in HTML and PDF. -## Streaming +To build the documents -### link:streaming/http-to-cassandra/README.adoc[http-cassandra] - -A data pipeline demonstration that consumes data from an `http` endpoint and writes the payload to Cassandra database using the `cassandra` sink application. - -### link:streaming/http-to-mysql/README.adoc[http-mysql] - -A data pipeline demonstration that consumes data from an `http` endpoint and writes the payload to MySQL database using the `jdbc` sink application. - -## Task / Batch - -### link:tasks/simple-batch-job/README.adoc[simple-batch-job] - -A simple Spring Batch job running as short-lived task in Cloud Foundry. - -## Functions - -### link:functions/README.adoc[functions-in-scdf] - -A simple demonstration of Spring Cloud Function and Spring Cloud Data Flow integration. - -## Analytics - -### link:analytics/twitter-analytics/README.adoc[twitter-analytics] - -A data pipeline demonstration that consumes data from twitter-firehose using `twitterstream` source application and computes simple analytics over data-in-transit with the help of `field-value-counter` sink application. - -## Data Science - -### link:datascience/species-prediction/README.adoc[species-prediction] - -A simple demonstration to walkthrough the steps to compute real-time predictions using https://en.wikipedia.org/wiki/Predictive_Model_Markup_Language[PMML] application. +``` +$mvn package +``` diff --git a/custom-apps/celsius-converter-processor/README.adoc b/custom-apps/celsius-converter-processor/README.adoc deleted file mode 100644 index 99d3f99..0000000 --- a/custom-apps/celsius-converter-processor/README.adoc +++ /dev/null @@ -1,172 +0,0 @@ -# Custom Spring Cloud Stream Processor -======================================= - -### Creating the project - -Today we're going to talk about how to create a custom Spring Cloud Stream application and running it on Spring Cloud Data Flow. -We're going to go through all the steps for making a simple processor that will allow you to convert temperature from Fahrenheit to Celsius. -We will be running the demo locally, but all the steps will work in a Cloud Foundry environment as well. -The first step is to create a new spring cloud stream project. -We can do that by going to http://start.spring.io/, which is the spring initializer. - -Choose the group as `demo.celsius.converter` and enter artifact name as celsius-converter-processor. -Next, we need to choose a message transport binding as a dependency for the custom app. -There are options for choosing ***rabbitmq*** or ***kafka*** as the message transport. -For this demo, we choose rabbit by typing rabbit in the search bar under "Search for dependencies" and then selecting "stream rabbit". - -Hit the generate project button and then open the new project in an IDE of your choice. - -### Developing the app - -Now we're at a point where we can actually create our custom app. In our Spring Cloud Stream application, the minimum configuration is going to require two Java class files. -* CelsiusConverterProcessorAplication.java -* CelsiusConverterProcessorConfiguration.java - -Spring Cloud Stream applications are stand alone spring boot applications that can be run on their own. -Spring Cloud Data Flow is the orchestration layer that ties these individual Spring Cloud Stream apps together. - -Since we named the project as celsius-converter-processor, the initializer created a class called CelsiusConverterProcessorAplication. -We are creating a transformer that takes a Fahrenheit input and converts it to Celsius. -We want to follow the same naming convention as the application file, so create a new file in the same directory called `CelsiusConverterProcessorConfiguration.java`. - -##### CelsiusConverterProcessorConfiguration.java -``` -@EnableBinding(Processor.class) -public class CelsiusConverterProcessorConfiguration { - - @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public int convertToCelsius(String payload) { - int fahrenheitTemperature = Integer.parseInt(payload); - return (farenheitTemperature-30)/2; - } -} -``` - -There are two important spring annotations that we introduced in the above code. -First we annotated the class with **@EnableBinding(Processor.class)**. -Second we created a method and annotated it with ***@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)***. -By adding these two annotations we are basically classifying this stream app as a Processor(as opposed to a source or a sink). -This allows us to specify that the application is receiving input from upstream(Processor.input) and send the output data downstream(Processor.OUTPUT). - -The convertToCelsius method takes a `String` as input for Fahrenheit and then returns the converted Celsius as an integer. -This method is very simple, but that is also the beauty of this programming style. -We can add as much logic as we want to this method to enrich this processor. -As long as we annotate it properly and return valid output, it works as a proper Spring Cloud Stream processor. - -Once we're done putting together the app, move into the origin of the project directory and build a deployable jar with Maven, possibly on the command line. -``` -cd -mvn clean install - -Make sure you have a running instance of RabbitMQ https://www.rabbitmq.com/ - -java -jar target/celsius-converter-processor-0.0.1-SNAPSHOT.jar -``` - -If all goes well, we should have a running standalone Spring Boot Application. -Once we verify that the app is started and running without any errors, we can stop it. - -## Deploying Locally on Spring Cloud Data Flow - -#### Prerequisites - -In order to get started, make sure that you have the following components: - -* Local build of https://github.com/spring-cloud/spring-cloud-dataflow [Spring Cloud Data Flow] -* Running instance of RabbitMQ https://www.rabbitmq.com/ - - - Launch the locally built `server` - -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar -``` - -Connect to Spring Cloud Data Flow's `shell` - -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - -``` - - -[Register](https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app) RabbitMQ binder variant of out-of-the-box applications -``` -dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven -``` - -``` -app register --type processor --name convertToCelsius --uri --force -``` - -Create the stream. -We want to create a stream that uses the out of the box apps `http` and `log` and then connect them with our custom celsius converter app. - -``` -dataflow:>stream create --name convertToCelsiusStream --definition "http --port=9090 | convertToCelsius | log" --deploy - -Created and deployed new stream 'convertToCelsiusStream' -``` - -Verify the stream is successfully deployed - -``` -dataflow:>stream list -``` - -Verify that the apps have successfully deployed - -``` -dataflow:>runtime apps -``` - -Since we are running locally, note the file location of the logs. - - -``` -2016-09-27 10:03:11.988 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.log instance 0 - Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984991968/convertToCelsiusStream.log -2016-09-27 10:03:12.397 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.convertToCelsius instance 0 - Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984992392/convertToCelsiusStream.convertToCelsius -2016-09-27 10:03:14.445 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.http instance 0 - Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984994440/convertToCelsiusStream.http -``` - - Post sample data pointing to the `http` endpoint: `http://localhost:9090` [`9090` is the `server.port` we specified for the `http` source in this case] - - -``` -dataflow:>http post --target http://localhost:9090 --data 76 -> POST (text/plain;Charset=UTF-8) http://localhost:9090 76 -> 202 ACCEPTED -``` - -Open the log file for the convertToCelsiusStream.log app to see the output of our stream -``` -tail -f /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-7563139704229890655/convertToCelsiusStream-1474990317406/convertToCelsiusStream.log/stdout_0.log -``` -You should see the temperature you posted converted to Celsius! -``` -2016-09-27 10:05:34.933 INFO 95616 --- [CelsiusStream-1] log.sink : 23 -``` - -In conclusion, we created a simple Spring Cloud Stream processor that converts the incoming Fahrenheit temperature data to Celsius. -We ran it first as a standalone Spring Boot microservice application and then took the same app to Spring Cloud Data Flow to orchestrate it to be part of a stream that contains other apps. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a7f2eff --- /dev/null +++ b/pom.xml @@ -0,0 +1,315 @@ + + + 4.0.0 + spring-cloud-dataflow-samples + org.springframework.cloud + 1.0.0.BUILD-SNAPSHOT + + Spring Cloud Data Flow Samples + + ${basedir}/.. + 1.2.3.RELEASE + + + + + + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.3 + + + org.asciidoctor + asciidoctorj-pdf + 1.5.0-alpha.11 + + + + index.adoc + book + + true + warn + ${project.version} + ${project.artifactId} + ${version-type-lowercase} + ${spring-cloud-dataflow.version} + ${dataflow-version-type-lowercase} + ${dataflow-branch-or-tag} + https://raw.githubusercontent.com/spring-cloud/spring-cloud-dataflow/${dataflow-branch-or-tag}/spring-cloud-dataflow-docs/src/main/asciidoc + + + + ${org.springframework.cloud:spring-cloud-dataflow-core:jar.version} + ${org.springframework.cloud:spring-cloud-task-core:jar.version} + current-SNAPSHOT + current-SNAPSHOT + current-SNAPSHOT + current-SNAPSHOT + + + + + + generate-docbook + generate-resources + + process-asciidoc + + + docbook5 + + true + + + + + generate-html5 + prepare-package + + process-asciidoc + + + html5 + + + + + + + + + com.agilejava.docbkx + docbkx-maven-plugin + 2.0.15 + + ${basedir}/target/generated-docs + + 0 + index.xml + true + false + ${basedir}/src/main/docbook/xsl/pdf.xsl + 1 + 1 + + 1 + ${basedir}/src/main/docbook/xsl/xslthl-config.xml + + + + + + + + + net.sf.xslthl + xslthl + 2.1.0 + + + net.sf.docbook + docbook-xml + 5.0-all + resources + zip + runtime + + + + + html + + generate-html + + generate-resources + + ${basedir}/src/main/docbook/xsl/html-multipage.xsl + ${basedir}/target/docbook/html + true + + + + + + + + + + + + + + + + + + + + + + + + net.radai + grep-maven-plugin + 1.0 + + + + grep + + test + + + + target/generated-docs/index.html + Unresolved directive in .*\.adoc - include:: + true + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + ant-contrib + ant-contrib + 1.0b3 + + + ant + ant + + + + + org.apache.ant + ant-nodeps + 1.8.1 + + + org.tigris.antelope + antelopetasks + 3.2.10 + + + + + package-and-attach-docs-zip + package + + run + + + + + + + + + + + + + + + + setup-maven-properties + validate + + run + + + true + + + + + + + + + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.9.1 + + + attach-zip + + attach-artifact + + + + + + ${project.build.directory}/${project.artifactId}-${project.version}.zip + + zip;zip.type=docs;zip.deployed=false + + + + + + + + + diff --git a/src/main/asciidoc/Guardfile b/src/main/asciidoc/Guardfile new file mode 100644 index 0000000..bdd4d72 --- /dev/null +++ b/src/main/asciidoc/Guardfile @@ -0,0 +1,20 @@ +require 'asciidoctor' +require 'erb' + +guard 'shell' do + watch(/.*\.adoc$/) {|m| + Asciidoctor.render_file('index.adoc', \ + :in_place => true, \ + :safe => Asciidoctor::SafeMode::UNSAFE, \ + :attributes=> { \ + 'source-highlighter' => 'prettify', \ + 'icons' => 'font', \ + 'linkcss'=> 'true', \ + 'copycss' => 'true', \ + 'doctype' => 'book'}) + } +end + +guard 'livereload' do + watch(%r{^.+\.(css|js|html)$}) +end diff --git a/analytics/twitter-analytics/README.adoc b/src/main/asciidoc/analytics/twitter-analytics/main.adoc similarity index 70% rename from analytics/twitter-analytics/README.adoc rename to src/main/asciidoc/analytics/twitter-analytics/main.adoc index 47198a3..d08121b 100644 --- a/analytics/twitter-analytics/README.adoc +++ b/src/main/asciidoc/analytics/twitter-analytics/main.adoc @@ -1,80 +1,55 @@ +[[spring-cloud-data-flow-samples-twitter-analytics-overview]] :sectnums: -= Twitter Analytics +:docs_dir: ../.. +=== Twitter Analytics -In this demonstration, you will learn how to orchestrate a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from _TwitterStream_ and compute simple analytics over data-in-transit using _Field-Value-Counter_. +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from _TwitterStream_ and compute simple analytics over data-in-transit using _Field-Value-Counter_. -We will begin by discussing the steps to prep, configure and operationalize Spring Cloud Data Flow's `Local` server. +We will take you through the steps to configure Spring Cloud Data Flow's `Local` server. -== Using Local Server +==== Prerequisites -=== Prerequisites - -Make sure that you have the following components: - -* Local build of link:https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] * Running instance of link:http://redis.io/[Redis] * Running instance of link:http://kafka.apache.org/downloads.html[Kafka] * Twitter credentials from link:https://apps.twitter.com/[Twitter Developers] site -=== Running the Sample Locally +==== Building and Running the Demo -. Launch the `local-server` +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Kafka binder + -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar - -``` +include::{docs_dir}/maven-access.adoc[] + - -. Connect to Spring Cloud Data Flow's `shell` -+ -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] Kafka binder variant of out-of-the-box applications -+ - ``` dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven ``` - + + . Create and deploy the following streams + ``` -(1) dataflow:>stream create tweets --definition "twitterstream --consumerKey= --consumerSecret= --accessToken= --accessTokenSecret= | log" +dataflow:>stream create tweets --definition "twitterstream --consumerKey= --consumerSecret= --accessToken= --accessTokenSecret= | log" Created new stream 'tweets' - -(2) dataflow:>stream create tweetlang --definition ":tweets.twitterstream > field-value-counter --fieldName=lang --name=language" --deploy +``` ++ +``` +dataflow:>stream create tweetlang --definition ":tweets.twitterstream > field-value-counter --fieldName=lang --name=language" --deploy Created and deployed new stream 'tweetlang' - -(3) dataflow:>stream create tagcount --definition ":tweets.twitterstream > field-value-counter --fieldName=entities.hashtags.text --name=hashtags" --deploy +``` ++ +``` +dataflow:>stream create tagcount --definition ":tweets.twitterstream > field-value-counter --fieldName=entities.hashtags.text --name=hashtags" --deploy Created and deployed new stream 'tagcount' - -(4) dataflow:>stream deploy tweets +``` ++ +``` +dataflow:>stream deploy tweets Deployed stream 'tweets' ``` ++ NOTE: To get a consumerKey and consumerSecret you need to register a twitter application. If you don’t already have one set up, you can create an app at the link:https://apps.twitter.com/[Twitter Developers] site to get these credentials. The tokens ``, ``, ``, and `` are required to be replaced with your account credentials. + @@ -88,7 +63,8 @@ dataflow:>stream list . Notice that `tweetlang.field-value-counter`, `tagcount.field-value-counter`, `tweets.log` and `tweets.twitterstream` link:https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as Spring Boot applications within the `local-server`. + -``` +[source,console,options=nowrap] +---- 2016-02-16 11:43:26.174 INFO 10189 --- [nio-9393-exec-2] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:field-value-counter-sink:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-6990537012958280418/tweetlang-1455651806160/tweetlang.field-value-counter 2016-02-16 11:43:26.206 INFO 10189 --- [nio-9393-exec-3] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:field-value-counter-sink:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 @@ -97,11 +73,13 @@ dataflow:>stream list Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-6990537012958280418/tweets-1455651806800/tweets.log 2016-02-16 11:43:26.813 INFO 10189 --- [nio-9393-exec-4] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:twitterstream-source:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-6990537012958280418/tweets-1455651806800/tweets.twitterstream -``` +---- + . Verify that two `field-value-counter` with the names `hashtags` and `language` is listing successfully + -``` + +[source,console,options=nowrap] +---- dataflow:>field-value-counter list ╔════════════════════════╗ ║Field Value Counter name║ @@ -109,11 +87,12 @@ dataflow:>field-value-counter list ║hashtags ║ ║language ║ ╚════════════════════════╝ -``` +---- + . Verify you can query individual `field-value-counter` results successfully + -``` +[source,console,options=nowrap] +---- dataflow:>field-value-counter display hashtags Displaying values for field value counter 'hashtags' ╔══════════════════════════════════════╤═════╗ @@ -144,7 +123,7 @@ Displaying values for field value counter 'language' ║.. │ ...║ ╚═════╧═════╝ -``` +---- + . Go to `Dashboard` accessible at `http://localhost:9393/dashboard` and launch the `Analytics` tab. From the default `Dashboard` menu, select the following combinations to visualize real-time updates on `field-value-counter`. @@ -158,9 +137,9 @@ Displaying values for field value counter 'language' .. Stream as `hashtags` .. Visualization as `Bubble-Chart` or `Pie-Chart` -image::images/twitter_analytics.png[Twitter Analytics Visualization] +image::twitter_analytics.png[Twitter Analytics Visualization, scaledwidth="50%"] -== Summary +==== Summary In this sample, you have learned: diff --git a/src/main/asciidoc/cloudfoundry-server.adoc b/src/main/asciidoc/cloudfoundry-server.adoc new file mode 100644 index 0000000..6f5f0c9 --- /dev/null +++ b/src/main/asciidoc/cloudfoundry-server.adoc @@ -0,0 +1,66 @@ + +The Cloud Foundry Data Flow Server is Spring Boot application available for http://cloud.spring.io/spring-cloud-dataflow/#platform-implementations/[download] or you can https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[build] it yourself. +If you build it yourself, the executable jar will be in `spring-cloud-dataflow-server-cloudfoundry/target` + +NOTE: Although you can run the Data Flow Cloud Foundry Server locally and configure it to deploy to any Cloud Foundry instance, we will +deploy the server to Cloud Foundry as recommended. + +. Verify that CF instance is reachable (Your endpoint urls will be different from what is shown here). ++ + +``` +$ cf api +API endpoint: https://api.system.io (API version: ...) + +$ cf apps +Getting apps in org [your-org] / space [your-space] as user... +OK + +No apps found +``` +. Follow the instructions to deploy the https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle[Spring Cloud Data Flow Cloud Foundry server]. Don't worry about creating a Redis service. We won't need it. If you are familiar with Cloud Foundry +application manifests, we recommend creating a manifest for the the Data Flow server as shown https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#sample-manifest-template[here]. ++ +WARNING: As of this writing, there is a typo on the `SPRING_APPLICATION_JSON` entry in the sample manifest. `SPRING_APPLICATION_JSON` must be followed by `:` and The JSON string must be +wrapped in single quotes. Alternatively, you can replace that line with `MAVEN_REMOTE_REPOSITORIES_REPO1_URL: https://repo.spring.io/libs-snapshot`. If your Cloud Foundry installation is behind a firewall, you may need to install the stream apps used in this sample in your internal Maven repository and https://docs.spring.io/spring-cloud-dataflow/docs/1.3.0.M2/reference/htmlsingle/#getting-started-maven-configuration[configure] the server to access that repository. +. Once you have successfully executed `cf push`, verify the dataflow server is running ++ + +``` +$ cf apps +Getting apps in org [your-org] / space [your-space] as user... +OK + +name requested state instances memory disk urls +dataflow-server started 1/1 1G 1G dataflow-server.app.io +``` + +. Notice that the `dataflow-server` application is started and ready for interaction via the url endpoint + +. Connect the `shell` with `server` running on Cloud Foundry, e.g., `http://dataflow-server.app.io` ++ +``` +$ cd +$ java -jar spring-cloud-dataflow-shell-.jar + + ____ ____ _ __ + / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | + \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | + ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | + |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| + ____ |_| _ __|___/ __________ + | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ + | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ + | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / + |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ + + +Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". +server-unknown:> +``` ++ +``` +server-unknown:>dataflow config server http://dataflow-server.app.io +Successfully targeted http://dataflow-server.app.io +dataflow:> +``` diff --git a/src/main/asciidoc/coalesce.rb b/src/main/asciidoc/coalesce.rb new file mode 100644 index 0000000..829f6b5 --- /dev/null +++ b/src/main/asciidoc/coalesce.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby + +# This script coalesces the AsciiDoc content from a document master into a +# single output file. It does so by resolving all preprocessor directives in +# the document, and in any files which are included. The resolving of include +# directives is likely of most interest to users of this script. +# +# This script works by using Asciidoctor's PreprocessorReader to read and +# resolve all the lines in the specified input file. The script then writes the +# result to the output. +# +# The script only recognizes attributes passed in as options or those defined +# in the document header. It does not currently process attributes defined in +# other, arbitrary locations within the document. + +# TODO +# - add cli option to write attributes passed to cli to header of document +# - escape all preprocessor directives after lines are processed (these are preprocessor directives that were escaped in the input) + +require 'asciidoctor' +require 'optparse' + +options = { attributes: [], output: '-' } +OptionParser.new do |opts| + opts.banner = 'Usage: ruby asciidoc-coalescer.rb [OPTIONS] FILE' + opts.on('-a', '--attribute key[=value]', 'A document attribute to set in the form of key[=value]') do |a| + options[:attributes] << a + end + opts.on('-o', '--output FILE', 'Write output to FILE instead of stdout.') do |o| + options[:output] = o + end +end.parse! + +unless (source_file = ARGV.shift) + warn 'Please specify an AsciiDoc source file to coalesce.' + exit 1 +end + +unless (output_file = options[:output]) == '-' + if (output_file = File.expand_path output_file) == (File.expand_path source_file) + warn 'Source and output cannot be the same file.' + exit 1 + end +end + +# NOTE first, resolve attributes defined at the end of the document header +# QUESTION can we do this in a single load? +doc = Asciidoctor.load_file source_file, safe: :unsafe, header_only: true, attributes: options[:attributes] +# NOTE quick and dirty way to get the attributes set or unset by the document header +header_attr_names = (doc.instance_variable_get :@attributes_modified).to_a +header_attr_names.each {|k| doc.attributes[%(#{k}!)] = '' unless doc.attr? k } + +doc = Asciidoctor.load_file source_file, safe: :unsafe, parse: false, attributes: doc.attributes +# FIXME also escape ifdef, ifndef, ifeval and endif directives +# FIXME do this more carefully by reading line by line; if input differs by output by leading backslash, restore original line +lines = doc.reader.read.gsub(/^include::(?=.*\[\]$)/m, '\\include::').gsub(/^:docs_dir:.*/,'') + +if output_file == '-' + puts lines +else + File.open(output_file, 'w') {|f| f.write lines } +end diff --git a/datascience/species-prediction/README.adoc b/src/main/asciidoc/datascience/species-prediction/main.adoc similarity index 74% rename from datascience/species-prediction/README.adoc rename to src/main/asciidoc/datascience/species-prediction/main.adoc index b5bffeb..fee7a72 100644 --- a/datascience/species-prediction/README.adoc +++ b/src/main/asciidoc/datascience/species-prediction/main.adoc @@ -1,62 +1,28 @@ :sectnums: -= Species Prediction +:docs_dir: ../.. +=== Species Prediction In this demonstration, you will learn how to use https://en.wikipedia.org/wiki/Predictive_Model_Markup_Language[PMML] model in the context of streaming data pipeline orchestrated by http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow]. -We will begin by discussing the steps to prep, configure and operationalize Spring Cloud Data Flow's `Local` server, a Spring Boot application. +We will present the steps to prep, configure and rub Spring Cloud Data Flow's `Local` server, a Spring Boot application. -== Using Local Server +==== Prerequisites -=== Prerequisites - -Make sure that you have the following components: - -* Local build of link:https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] * Running instance of link:http://kafka.apache.org/downloads.html[Kafka] -=== Running the Sample Locally +==== Building and Running the Demo -. Launch the `local-server` +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Kafka binder + -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar - -``` +include::{docs_dir}/maven-access.adoc[] + - -. Connect to Spring Cloud Data Flow's `shell` -+ -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] Kafka binder variant of out-of-the-box applications -+ - ``` dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven ``` - + . Create and deploy the following stream + @@ -79,16 +45,17 @@ dataflow:>stream list . Notice that `pmmlTest.http`, `pmmlTest.pmml`, and `pmmlTest.log` link:https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running within the `local-server`. + -``` +[source,console,options=nowrap] +---- 2016-02-18 06:36:45.396 INFO 31194 --- [nio-9393-exec-1] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:log-sink:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-3038434123335455382/pmmlTest-1455806205386/pmmlTest.log 2016-02-18 06:36:45.402 INFO 31194 --- [nio-9393-exec-1] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:pmml-processor:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-3038434123335455382/pmmlTest-1455806205386/pmmlTest.pmml 2016-02-18 06:36:45.407 INFO 31194 --- [nio-9393-exec-1] o.s.c.d.d.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:http-source:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-3038434123335455382/pmmlTest-1455806205386/pmmlTest.http -``` +---- + -. Post sample data pointing to the `http` endpoint: `http://localhost:9001` [`9001` is the `server.port` we specified for the `http` source in this case] +. Post sample data to the `http` endpoint: `http://localhost:9001` (`9001` is the `port` we specified for the `http` source in this case) + ``` dataflow:>http post --target http://localhost:9001 --contentType application/json --data "{ \"sepalLength\": 6.4, \"sepalWidth\": 3.2, \"petalLength\":4.5, \"petalWidth\":1.5 }" @@ -157,7 +124,7 @@ NOTE: `petalWidth` value changed from `1.5` to `1.8` } ``` -== Summary +==== Summary In this sample, you have learned: diff --git a/src/main/asciidoc/docinfo.html b/src/main/asciidoc/docinfo.html new file mode 100644 index 0000000..49e6edf --- /dev/null +++ b/src/main/asciidoc/docinfo.html @@ -0,0 +1,76 @@ + + + + + + + + + diff --git a/functions/README.adoc b/src/main/asciidoc/functions/main.adoc similarity index 83% rename from functions/README.adoc rename to src/main/asciidoc/functions/main.adoc index 5bbeb2d..ba63c20 100644 --- a/functions/README.adoc +++ b/src/main/asciidoc/functions/main.adoc @@ -1,70 +1,34 @@ :sectnums: -= Functions in Spring Cloud Data Flow +:docs_dir: .. +=== Functions in Spring Cloud Data Flow In this sample, you will learn how to use https://github.com/spring-cloud/spring-cloud-function[Spring Cloud Function] based streaming applications in Spring Cloud Data Flow. To learn more about Spring Cloud Function, check out the http://cloud.spring.io/spring-cloud-function/[project page]. -== Prerequisites +==== Prerequisites -Make sure that you have the following components: - -* Local build of link:https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Local build of link:https://github.com/spring-cloud/spring-cloud-function[Spring Cloud Function] -* Running instance of RabbitMQ +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] +* A local build of link:https://github.com/spring-cloud/spring-cloud-function[Spring Cloud Function] +* A running instance of https://www.rabbitmq.com/[Rabbit MQ] * General understanding of the out-of-the-box https://github.com/spring-cloud-stream-app-starters/function/blob/master/spring-cloud-starter-stream-app-function/README.adoc[function-runner] application -=== Running the Sample Locally +==== Building and Running the Demo -. Launch the `Local-server` +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder + -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar - -``` +include::{docs_dir}/maven-access.adoc[] + - -. Connect the `shell` -+ - -[source,bash] ----- -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - ----- - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the RabbitMQ-binder variant of the out-of-the-box applications -+ - ``` dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven ``` - + . Register the out-of-the-box https://github.com/spring-cloud-stream-app-starters/function/blob/master/spring-cloud-starter-stream-app-function/README.adoc[function-runner] application (_we will use the `1.0.0.BUILD-SNAPSHOT` built by the Spring CI system_) + - ``` dataflow:>app register --name function-runner --type processor --uri http://repo.spring.io/libs-snapshot/org/springframework/cloud/stream/app/function-app-rabbit/1.0.0.BUILD-SNAPSHOT/function-app-rabbit-1.0.0.BUILD-SNAPSHOT.jar --metadata-uri http://repo.spring.io/libs-snapshot/org/springframework/cloud/stream/app/function-app-rabbit/1.0.0.BUILD-SNAPSHOT/function-app-rabbit-1.0.0.BUILD-SNAPSHOT-metadata.jar ``` - + . Create and deploy the following stream + @@ -72,29 +36,33 @@ dataflow:>app register --name function-runner --type processor --uri http://repo dataflow:>stream create foo --definition "http --server.port=9001 | function-runner --function.className=com.example.functions.CharCounter --function.location=file:////spring-cloud-function-samples/function-sample/target/spring-cloud-function-sample-1.0.0.BUILD-SNAPSHOT.jar | log" --deploy ``` ++ NOTE: Replace the `` with the correct path. + NOTE: The source core of `CharCounter` function is in Spring cloud Function's https://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample/src/main/java/com/example/functions/CharCounter.java[samples repo]. -+ - + . Verify the stream is successfully deployed. + +``` +dataflow:>stream list +``` ++ +//// +TODO: Doesn't render correctly in PDF [source,bash,options="nowrap"] ---- -dataflow:>stream list ╔══════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤════════════╗ ║Stream│ Stream Definition │ Status ║ ║ Name │ │ ║ ╠══════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪════════════╣ ║foo │http --server.port=9001 | function-runner --function.className=com.example.functions.CharCounter │All apps ║ -║ │--function.location=file:////spring-cloud-function-samples/function-sample/target/spring-cloud-function-sample-1.0.0.BUILD- │have been ║ +║ │--function.location=file:////spring-cloud-function-samples/function-sample/target/spring-cloud-function-sample-1.0.0.BUILD- │have been ║ ║ │| log │successfully║ ║ │ │deployed ║ ╚══════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╧════════════╝ ---- - +//// + . Notice that `foo-http`, `foo-function-runner`, and `foo-log` link:https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as Spring Boot applications and the log locations will be printed in the Local-server console. + @@ -116,7 +84,7 @@ dataflow:>stream list ---- + -. Post sample data pointing to the `http` endpoint: `http://localhost:9001` [`9001` is the `server.port` we specified for the `http` source in this case] +. Post sample data to the `http` endpoint: `http://localhost:9001` (`9001` is the `port` we specified for the `http` source in this case) + ``` dataflow:>http post --target http://localhost:9001 --data "hello world" @@ -146,7 +114,7 @@ $ tail -f /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gs/T/spring-cloud-dataflow .... ---- -== Summary +==== Summary In this sample, you have learned: diff --git a/src/main/asciidoc/geode-setup.adoc b/src/main/asciidoc/geode-setup.adoc new file mode 100644 index 0000000..8968808 --- /dev/null +++ b/src/main/asciidoc/geode-setup.adoc @@ -0,0 +1,13 @@ + +If you do not have access an existing Geode installation, install http://geode.apache.org[Apache Geode] or +http://geode.apache.org/[Pivotal Gemfire] and start the `gfsh` CLI in a separate terminal. +``` + _________________________ __ + / _____/ ______/ ______/ /____/ / + / / __/ /___ /_____ / _____ / + / /__/ / ____/ _____/ / / / / +/______/_/ /______/_/ /_/ 1.2.1 + +Monitor and Manage Apache Geode +gfsh> +``` diff --git a/src/main/asciidoc/images/scdf-dashboard.png b/src/main/asciidoc/images/scdf-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..7f534ccd8aed83d07dd7a3321a15708e595da576 GIT binary patch literal 112258 zcmaI7WmsIxwk`|_B)Gdf1Shz=LvXhM!QEYhH6GlZ;L^Bz)3^j_+!{%632rxQ@AI9r zzjN2R^Qj+mR?SgkzN4z1@s6r70ji&5QIUv{U|?WS<>jQ*VPN19U|`^K5Z?W%0dJWl zz`!8Y*+@#N%1cU8sJc2?+Spsbz{mko)81=hFB5^!CQ9)2B}%Y;u}kFAv3!4aFC!q* zrVzXpm)4ZR)A`I&E~kO#j49RM4AX!&6zZU++1Eo66WqayS6|TZR%l@LcFOOp>ov#e z^vu8gD&NWRRQTX+uxmaw&iB5LFeOMor2F$&Cq~Mx=>lOAgM|`dk;D=Pm9ZP%ybXY@ zY`-|m`UyYt+Z*D&ap3Ds_Pkexnw@SL&jnCIT4duT@P!g9&{%qo2&0vyYYX zi>gU1B|*t;fVox0?U;EpI}@AeIQkL+1`a8bS^*~biENUSvkkEvJv_dlA{dNca2(M< z&HHUok{^FByrQD&`#r(f1Mqb>`J8uJ7eF7GOtHP}l!@6Nmrtj(UHvGU4h>@BmKM52 zQ|4j-P}O~Q|59M5o!&JjI}ob-8qB|cWw}4?T(rbwAKz|MJL@(9ZM&ZU^6|%VgGpwe z8lT)ff0D##!z(_)e|YJ^dgW^ggZ@~P+~>(7Hu49!IGPi;j$PP^#4MomAF=*Sz> zpry@|uw5qlo7=AVI~Yzqb^gGX?B2JFN|_&wadS)Gg*Q#QA8^M9l(Ew~_q^b!$cwO0 zOI_LvboB4@0idLOXV?sS2 zmeIwJ;yEkheVkODtcJ}H`PvwC(fP<}g=~hg?`ntSxoikzFz1QP>@l64V?q5XhFK2FQh**i`%oP$>@34{^A45*M=At27#T~P5hH|~ z0@?nZPXWv^oS!&hIUIKZ8VNjD9GUMeYcSK+yEatcKI$3th(1O3cXWL;aN^!kNV62u za-=^(Vkz84-noXYQJOFiM2DIcz{$Y?3Yo2uHDPeYEmUze(VtOrBUr^C1&%*qxnSZX zoC>Ge-)MXms75*(i1|#M0sq)nc<#yvYm90&(0=aO23H%A&^LJwfA?4jwhJ7^ zm#`3Pis2~KooG0USvesp2_C9@IS%zWE-D8(dRP2kvc{D8?0hJwgF^)7#~j8P>?rt+ zM2(mlQ6C29O|v-C*}XX4W^hdKGUHZ-au2MSE-%U1zwt!nK{tr40p$%C58r%_tjFdf zi4U0@)Pr_8tF_Ur`5IC>iq;}R;*W+=cZM&#yQnr0&VteV+|Ga93Hg6`L3j~*K?_89 z{U%0Njy-`$7G@n9oG8gaM?#lFy+(}ngc%u?Orw`X zHX4GXpg`q7mzqcU=^fo?gCL~1{|ag=t~e79;B_L4rD1eCa=peKW=(V~H- zw(aL+`~Odcul?DbE3U##xnz?2PX^5pbn6J~POUhN*kmui2} zx28WoF2&*uqYb;rutBfhEWlU8yCAo)SQ|Q9^}mO=fVT?g3-=GF3nvSoj#iTP0(}7) zMYBY!q_8VQD2OZArJykwY5SHc>9pwVGafLJ>jaj+sUoO^tE$$iP;0OFSX=r1u!2#O zMXS5~K_RYizdEg?MfN0TrCdOHT`jk+NA|hv0r|U7GDyiZjh&4H%%#cI#Wh5vMPx*j zoaLKkn#G@`oTbtvr_ZB*q3_ou&@|k%(EQxg*hJh!eu&{=?~dhh^UM9ve`aAWZf3o5 zwMek2tN^??K5sYUSFN((^~0pbq$X$@#_F?qqJ915Rtu%QwM~Y#uA}!j0#C!o9pV$- zL*pnT>rU1BdSBCg4p4?gj_KNGq0a;C7u=&9HXJ_Pa(-&Ri;Q9f@B=uTxs*ACtsh2| zrY2UI!PS$;HSLA`kgm0-JotryL9=A(Do{2^CI*T}uIs;-eS+giigZ2`~j$gFepCiaA0kg3zX6Y3eXLcB`9O5Q@QSJX=5INDG9 z6)g*mB$6>QQ1-idEHokh`4iD6k}}&et10~{p#%K`(==EnfJfN%3TR$>*L7^~YgO*i zJBTOm(BvG;X3e(hrE1!M4pG=nyS6`pIo;@FhZy*==cdc;2FrIySaXw8!?rW)CcK{ zV*TQa+3nfpS*YTA`l*pX(}b(uM#ILQ?>L0Dw?)E6dMvt;sZ_^RJ1?q#SZatQ{(b;) zOVe%Gd>M!fG&j^a6**PR<8(rI;+mqYWpL!%pzL7?r0J(L^%}4)(lB$`Vd`P(jeVsX zWvcl2OVU;BvT(N|B`W2+ri881p-o5*g`Trb>PlsERY$nYfRO2{ZRdiYP6EJRs@X<$ z<+5qfU0~&S4d*DP7aRQxpJj@bzae(d{*eB1b7(U!gs^tC#gT80`l{?Y<9h9yRF6n6 zyYU@QJ&&eC7|*cd@lr|i2d_ER7Awzn%OCr@lfC;H`#5`Dn^?e779DP0L9cVc=`*6s zl1nL{0E3fO?ZAZlyw?B-PmDw9YR}%)WgUJ79uB_$hh045*Z$+kB=YYqV5hSc(`IPj zr?pT0QyWH~IuE12#C(i-=k<8vxG}hv+@o^LR$$EHa~8p|7WUe=qxza9br*l~v_Y6=UbjO~^fs9zlNm zG`e5*pkKNYx>6Sj7x{1$dc?Y50D+Ke^LG`)I%4p~lIeNw-l(+}*TfCSX(`8k4>jM) zxLbvyX7<)2zNItgCKjIu>e zS?7EZWeV~H^Z#gHbJIBBoK9#(UNte2YhzymHb7@VBQdwE@J5Fn$8PtBxCu=7f_k|J zbpnRMZj+}gzm9ky29CPx);%^pSMzmgy?KWXhqgTy0ae#6CnqhZwCe|_eCzGbkdxC? zzhggM-zUEgzd_%#Tb84v-sw)!ONzbz>_|d%dU6ZVVUejIs;iQ_im|!FO_V^p!`4Gl z!7U!=E4`6M*{^H;>AhvoFBS~9{MSAg^$*U^QTHR6Y6-KeY-v3Nz90Pg?-|d~mqi(k zk9tM!%dYZy!BpUgji?Q!ZWjNtyVIFR(3#-yTX6oTl21y3Bd_Imz|-W(vZ-mz{78C; ze}B-2d)xEolkDkMuttT3hD3Z6=NuA+b>GDWOqcW{oGlJa(<)42iKX8zp?G7!GfK$o zP-DRF*lL(^oA(r4#4slA%+j((TqU`%2vXGZgnf8;Nq3Pyc338?x<^>7?bL<1uhC9W zFW$lUpJZoc*=J@w=*QqaVg%m+mN)$MKU%+@J%#Q$o%peRA$h8Lc|-FEe|@zN_(Nb} z^KCSB-F20f1k9ZrSWUk;nOU%UJ2?Mofq@b77Wi}PVBu~`;q74W=qBJTO!cof1peIr zRn104@vm3h?S!dxl~pMuom?#_xLLVa*{MX3C@3g|T)$Wfs7uNGm-wG2VJd5PcV_`M zHZLzPRxeIgCs!*r4t{=qHujHfA3w7Ed4t8x$I;!?o5j(M`rn=WfBi^VxS6}!IJ?_8 zIa2)9uc?`nhr2Kp)nAJK`}+5HT6o+1k0wXA|AO@gAlqLpY#glYZ2#T&A5o#dY6Vnn zye;f?rEDB59Nqrt5aIa9$0zhJf&Z)Ne^ma5sNR2wa`3VLr|5q){gMP>25}zy4GzN5C}5ZUpAE$d$AGaIPIOE8 z5AZ2Md?kY4mICP;J1UMt>-iAlD&$n4JQfO>b=CoG2#`8BkN@wzSa@4>V3 zhA2{Dyn~0QEL5~Yky98z?XKl4`mAeBAR#Fk%Rs;|P>`QbP6P-pD(&hb;g}p#?sh~( zWME*HGBzgr*w|3-07k2RwZ(36*bFh$(@|4%X(y}?z-nW76Fym#xLL~|O)OiaB-MY} z2b1#tPMp=-ru9vWYkP!6!)UW1<(qaS0763{GYv-Rb|FLBvzq|8U$l27Dt!BcO?_&b zk!F4y=ikr5JB6(xxPipP&%ck>iN89w6Ru--QnhF)a@njA^!N93lbM7|wkR>ky8;hs8J=rB#ZBQ@~0M9^j3AG2~m_23-2k) zu-(gvxqE(2Gxjrz0qM7+x-kUF@spS zC8(U-XtLt=8gO~zGD9KIb8IHb#$LtExDkfXPJPOi-8|F3Uv(idl&bV0Gjy!U!W~|N z^{WvD({a27Zs7Q+=xBF+gvDk_Mj{@&#d)QZRj^_wsk3?A5zzIT$R0Ol;5dh*^?UQn z5c%5I*T5%^sa(OcmN;Y@XMTk8PUi{)zxG`H7-AQkXz4W#5Zk#SUZ{#ipC~N+j&ckzfYf3$~i{{6C4egCEz3qgwj1wW>n@~dNi{c0q^QU7pUF`GWY@5M7! zAoDSuHo(QDX0|Xus0ZVl^JMywGv9SoMeSmwk$}fg+gZZ!)Osh7+e;8BhG1}#SaI5e zu{t6mV!)(&M$=tuTsaLHTNSb`0bt3%-^2>XvQk}-`br!4S=INuE{Y}fPyhJ!owEUD z!WaqMXZIh^j88 zVQsbxnP$WJr7*9c*GKCO=6A@V4+OBVux&k7D*ipTs8|AC67HHfKc@4#hh%F_CM!m& zNP;e*9|+v9#26qrqZGNRxp7V{j?&`drq4v@v_x^1)U4KXB>cH%YDAcHcwhApggxJ3 zjxtUenH?ztw8~k>)coQzpu3*-w2okoVY7O}k5pA4)5122ba?oTjPNWRkcnZO-rqa3 zf?7CM28_z`lASH1V%cr5XjWK#eSHVnQPHi2*Zyk6T6Bv8)cN<4OSNGm-nfWCNSW0O znsOFbgh?g&*jUDMv%pN2az}u_kRu^qU({E9mGxHc_}vi6NCpgF*fK{D{LZJG^>*&D z0SP6czViSuhVNxg`bxT|R(%`m`zQk!PgBIpAy;655wZ(Mnt4=xRjGs-0iHrp%K4gx zWoFPnd^9T@(Lz(QenzwP1_`w+%Ig$Jyei)mORz4PMjG*((&*KO&$Mozh1G%FyFKkF z46iR~hloG#s}qAjpd>MypGZ2N4Iyq;>=hi1 zL`$u$bX&3IJzgn}j81Y7EaJH&I6zwB+Q@l5YQ}uf-`wBd^Leww8?-n|8XJpTULiYE zozU<&Y=llsFej`SGJj(pxTiwH&`*Oyc~VjbM$DvqKQRi2w&RNgtOXm*2g*hB5KZW z?O_8s6~60VHwR7XKKhL4PwKG2{aIO2vO$7xTh|2;vS2Jh_*Kq3yYdVMcwTSx)>jG( zEU@nsFB4}5%P?I92D=9=j2Tmh7&0LqiLt|z$`j(#gIZjFToV@oNX?Y4A5gxRr`4wP z_nsY}Mzuz4soQ`mVuObuSJ0#DGqp~UM4oPM&Alt>%f+xEiGsX~;BH>`qtZ^wcPb3q z38`U9_d#e&0W0WW+UoP{4;5t+2@hU6HeM-9N}Zi&TwY*jbtEZ&+&Q%l>y$~j;b8j- z&4*}&l+v9QL)P&HTwKJMEEy^adh(W!NMQ>uJAcb(LkRAuwul*!!yp!bdr>i zP*qpIT-W7_R&*+iasbV4k8l#kNMgDQky6@NN&9yWEk_HhB<_;VP7J}bWK*ep#7~za z9}E3j@aD5}sl~F-f{Dt>?MwmTn8%A9tO~!37*wivi7; z`OL2O^qg(onIuWB>Ha! z0})Wr(ZRtbfj^gvJ82wkJ|M~~)SE(O2Gv;JOG*dNIo!r}j&t#zt=})vLxEW7*6Kta zqCJHWkB`HWy3A=2+OJy7r+G^Y$K;zWHJIk9I^yD#KZcZj(uX3R_E&58^0%{@YA>T~ z7AInhBXz4=97$tT364|am()w7)a zfwrhUE5Dnk!A%7Eb)|*kBTl4W2k>SY(9xvYqug;}Ul?#9M%llqb(6lrMaNw1F)|`m zQs~hvN5y2x7Sm7-eNnuL<<&j82$uy8(GS6g4cXovy!$(99P&=3AXwC#}Dth|X;o1^1{?L%O4~ktw9e}Ktr1QeKDBmn#yVDu5 zvi28TlCQJ|uG9w9)Jk|bI225R28Qm_(4QCBOD*P+QBK*hi54EGeuHPhpBViswn`V{ z$XSf320m+`U~W5{7i7=YDii;*(g45`#0Lk%%z3J*eY5dPtl!MeiA}A7e149IV@O3A z%#&sjoAD`1&8S-VV?oK1l}U6T`NM&+IF^(mG5uzJCM@HJuLFmEi&2g zFMvu|2`P&H;<)sRdu>FrGa~R=BDxNDmz8)CD?!4aip_?<{SGHQ`r8nv4ZEBQ!}D|= zktj%Y-J?!Z4Oy&NLeTY?;D(%!A`pNnlU;)5s?{Ii@P;>0-0I3m(ld8jFg|-Mz7KjoRb3&VLt+wPvN4? zbjKStOgG1?k!oJ??Ak%Of}UYz=ap$b0^tDeLb6UbFj`V-JBxm^H2_`OQ1eK{;tOtb zfntjMy2}FTpY@sTyfs5fO=QdlhL~54SmHKMDgIm|RIH!KfxO5E#Fgeb>WE*a26a)o zd4{My=FGGwW6Eghb{R3_-U2@JU%ZEcDjU$LsHrP|i^^3a3=Un^wMQk9O6zLE0>un7 z7Kqf>!;NC%yOR+z%w+lYswk$mw;)AczI=S6yQfg_qRa?J#qYHA<@hogr);XUt3 zVXrz*J?YNByfzy^G#X^4!UC^_fr5#@UU0=VCKFGKPNXD(#4_gjU}}I;-bz3|D^2WHGwQ1eQ16AfltYA^H2}&1?DmKtJW!DbWI7H>*}( zRA+o;Bx9tmDyJ>T*X`7!m13q_uvL$7JzfI7J$;;|0rGV%E4w!xcJ|nAE=cRvU@W*^ zW{SRuLh()+&nuU_AQ@^q5yE5iWGg+E28%rALx-x5_$)ik9s!ls#26SqSK@3B7IJw- zS!K+gKt;M{s1JZU{4`grkb@z0b|XUor(KJ>hl6goD3pj9prk-O_ywui;B94ggYNd> z4U@K%3G=-DczgJH@?&iH-$&lIl6}e)n&L;p#t=#KwT04hgi@D>Kjd24(vq%0+EByG zGS)TI=_q)G?GHs6%@%=kQSAU>VbF8r7Ct3G+SRytKT0fxEB~ zc-lB5j@$GpPv9>m4gxeK4=d|H*SVeW%!lUM+7^egRBoFA9vQ>eb3T4R;}b>O6G*KC zF?EDZr?$OtT!jt;l})g2RzOnUMS})1oU9t@_i< zLw{TnDDb!JP2CZl806F&wM(x8pK|pvRUDK}*7f3aMN3fbSnjFrNGz4lPs;g?Z zN0hA_W>VT!*efkJUNJPhdhNa}o~J7g8Gk6O;F%*GTH$c`Ji#}I)giskho?%Hhs&KT zN+w{g3oKgF5H;pw0_E?a_CKC<4>pj&ktC$6g(Y#br}PWq&7|w>LHwes+IsHuCDH`P zg4t|iij*t`Gy(zc%N{lJb;%cFk;vdX*qSJx;x{! zn3&FU`%d*wSJQE+`j(byb)ArkJR}dIs=7>FezLS7np#?F>N%QsE*^y*>!%LJ>pI*a zQG41|9`mHWvwv6}rFJ6YXPa3a++lb9=RJW=i)@5Suu2a5Dd@X8chJ16YwMT01>JC_ z9^E}W6;-3^1x6M4kCRJ6rcdi_=06=|H0Sq;0QEQBf~S4pnDppt)9(mwryS3Q=r(6i zLcm<>$`I?kcYK;1(5`!BB0Z|lU6=Wh3vq0W+YU4~XXN~Yd2$^a8`N+XIs9=ZwK%$> zkn-k8UizSik;e0EU#QE7WP-igBmk=XWwg0?pg@c3BK8w8uM_6&*>;A&o-CbAaq~Jv z2lu+cw}m(DYk%1kwW}AS1P!9RLo^+%T2(&@P>dOacaKSrOJ1Q|SFrMD`X=2weq%TZ zkMx$*6hc_8qYgAWCfB=uY`W2C6SZr|L@LSq1nIvEd7M44oUsuW7(bbJ+^f%rGW)#3 zc2O2VI<8F!A$le^ol63YXf5fxga^_nznKZC3YsyIIcuPHv&SHTc05tNQ@T;<`3B{6 zTj83w9>+v(s%6Ny>%4kl9lRTPRzv-VhgG`Y7d_#3e2t8aBQDI(J^~b*dOAd^JPOI` z1Ryr+uTS?V)Vl!<{_QT?wWqqxdO^lJlB`eX)c!Xhg}TlP>0-K6pVzMmGa@1zZRG~I z+~%&qZ8x^FLrhsP;On*BXpdi&+;-b+A z#RZxo4PkVvI_AvC7emK~Ymr?rkF;m2H;(-Cajk>$b<|sW+r3XGCj^GFf6Y!E;*b&` zbXKu?sBwf%!62RUl|stI{9C{e;P>&N63 zhq2Ig<*CE`s$DlftO?)ot%wH_85`8EiFj6>98PJ3lK2&ntj^|Lb&c_ttM9H!39Po{ zo3z~w3iKT7o_Ls&svK&z&?0M#R*^ua%vZCKU0CvW@_!RVZL1~4qV3=&=ZACC_kaYg zj>DYd&q8VBhtstVX_qsDD2f!^E(QuU0pV+J(CLOoTsh{g7!-QszW~Z4E!9}@$V45S zCN3b2wMWAYHdpS$tOplHtCa1T;1K)8tERa0PL(cZXZD+3m5ev9ZfNP{+`8=ZP(uLWuN4V=8Vaamj=CZ35qu?`p;v0an<`J!ND zj{;*{ovE}o3|>CoX7!X|$;S3m1e~^PaIS6S8@8{oAHGDgHnQU zO};J67ubxsc2g8hn4+|>TbO2PG!WiB41EjTZRD2`$yTY(kD(>YU)7%;t;(9l&+giM zo!`3xH9O?C)-KqJvQ>6ZVV5|)Epg&^jbm#vfwIQwY*-yQzfsPe#%I-3dghksu12lU>cpG|^1qB+R3|9gZ`B({)aB1qCQI52rm+)+{jG5BL?Cad4w)vuq ztwNk9yO$?LMzli?1)7-452Ne>g++*F^Q2478EsJm>WbrdEHv`+O>T{go2+=rS#ZOU zr0nb%+I&_{7m5H(gau#rPM!BZ?e0RLGjL=rmkRinCh=8^U+-(O3k%}>)NxI2x|al2 zAmzD{g+TPH6>eFzE9+#Idx?{XC}NM|9d%5^RZ5c`+I@vZ%hw$LupFVFLZkM7orl&E zzQN6i7oALDL;DUk54JGp*et#+wiJoZG+*_rUH}m?U~L~YFKe7<`5@qj975)1`_~Km zj&CQbsg8{}@S#={&8^A5+0%OY2wfh+PMP1b+a7-r%IQLyR`GqKm~&K@n`sp&{1z(E zjykq{ug4z={LQAaeH+h41r5ApmuXJ#0H^6-BFM(&L`TXZT{R5KrL*;t%Q2-osK|h0 z3o}kGKnIz6@#fh#S!Vm@358#8Yxy2hELT`trs@<$853x=Vj`%mmctkipwrXS1NFMH z8pe;mmi8|iXq4dwEXbJZ!a@7IW>&9KL!CyOzzmH1sIrFmZ9uB*#gIq9?1Dq*L7%IO z0^C3m@xu=2j$t~^(&sb|q#JN-5W8WU;1{5R>fsSN4~3_~=m3wj(5}VzdfC}HiS{7k zv6|TBdp)tp3Xz@p2zRWIv#Al_$A_EP|1O_{zk0k$&5BRTKEy$AI&~2gIbKtjQcwTU zfEu{g{=TL31jLfv(rMrJ&eDOJ)w@?yGsk%&rrrZY9F!44b0udSas(t1HQD0$WOFr% z9u!%^bIQBTjyd>Uc{Q?KWj(UjvBC5=%HyLQXx4)D>@Cll@R7p=QRZi&nvo^uol&#j zLAw@RA4?N3d2(clx!|DRl|Xr^XWMyTV~^S%OUtl1PL(OKB0)OMKbcjRX;O(TFX*PT zITt@MPK-I^hea>wli9r@F5P4Gdw3@+Z@RtTHQdw;)zQ5!QdX`U((4?+Qyi0d6HY&M zCFp6m=-@LGUKt!{b3(_e%&-K$pbV14lxokM#82bj9?jdQoXj!iQ!~npyAAOr97G+~ zxvl0V?`;q}*8W25&NdxkGpsdj=h+CFb#cJ?Qp7;B^1Q;ETlb{lB5_){x5+pC3{;s0 zh_#KViBDbq7Tp1Tkc`zeX~$=`9&uK>D>TH${+(6+3K@i-PCvTdLK>U!+Ys$&Xt_N= zIA|=&D@M;bkYnQ}uC^+UF21yH>e4&e$gcW*+i76Rd*(_aYMAt?jjr?jI8A>hS6&62 z+_+CrSgmPD_Gddqyxc0mvCU&<607QrsV=g4O)~&9q57R>;%bk1y6!>1Hl638yf#o1 zioGH7g+0&vx6a)G6C3nibZWRyV9>Z+N=3P7D#8k)hNdDx#m;Xf)pdu z5WH?9mC2zxB~>aL9)O5g?a{~xkft55(M3hki%FQGt1&v`eWxk|#pOsiNRh43c)4GHuU>p|ssCwD6ki4? zErhx-eAjq$EXu7f+y2gE{5S`N4crz=wPL>Jls_y5c8(@J%AGKbtcWnu4=dxgGbs$B zW}glB+4FtOSuj=u=Flfx!B?61vL?`W>e>A{GH8h`xXIY(bDDB6&&Q1+KTzj>PB{^f zfgtiT)OKTsj)(MgE<@_hc5vP!BfEXeGKrM{b4ren49mzdrJVCzQp8F?tR9gb8x~n6 zCWEuxzaNoYBc~?g^@^dypTz`$vT1KceT5+Mc$_uF;L`mr?{vQDLZG+sltr<5%go*^ z2j54sAcs?9D}|(}Le{EkU|KP<@$qNCSF`I3HsIg+ar1f{p=i@kKNave^>$L}s9Sf#1bd~u*-M#44#oMXd(2GpeuKX2%%6z(g=hH# z8sl`z*Gs5;Pr#FST&LN?ruJu|v)9vA zAsZ@7y#rMNk(1Z&{9#ZkX1)5wm)NcQ%>9NOSN4UI`l(i0%zBw=e_|)0pHyhk*EXKt zg}nG~q7MCujeUaBV5-2kneke+kt;cD&rh`%FKRCJXt!k^q?&oukARs3Ub|c^@a?Uo zAFUc}70R-;%$@=QhvIdh#o%DK` zv{*%)SoukgkjGftekFtVbX#Zab-_YU3oaufkGneZa2kt2RLqeFL4Y-!h+dDx_i5WN zh4KD@Uonf_p4fBx_474vbH5t7lT= zy$R|7G+qV^ED|9qYKaerog5)oO5twj*!o6(^EczWSO40^Nh{;bkUkc-^Q?t=?uV=f zYc!c@kgY?w$!{$c#L0LitGKy&HycQMg-ai^PoE=V9vf1zzx+RXkhm=j( z%N|^JPEat;z_Fn#C0WHPd&3@F3?ykDY`yqC!aec*K!1$4m)fjJJ!+QFk*yiXk&JQy zu64FU#U^@L$!4jVJmS7_Ci{-4X@m{sXb$=JY_uDmD6NUbA~fGF7=zKhJbuNzPjIUB z#BXQkD3mo3YWiU;3x1SC_Hn#YCz4O%ACGpu&Vwh&Jub&tfRAyq{`w~m)_3`c(L@WV zbczpF{xID&&8%yFnl4E`-JijqdiyP2f(N?X>DOuW+JEw%z!WMEMlDL{e5P>^#cO`) zRD%=o!@M2NWHbMAjtAt^bk0K`=5c>q9{2VQl@wxD>d&FP1zgwqBa*w2>Swo3BH8=< zV30X?IjnTVgNZrcnM02^1>#-ex)~lWCm@d)W^-BQ_N~eOJUS2b|H!HVa!(ISB1_>Wp-1C=Sl*w2g5u-6gtT=W2+vzB0?cFfzQ%aG3G=CVQ=#y3KL2?;q!AUn{u?;U{ZEa?;tS zv0L2#bE>V1M?yiEnC)|aez8FYN&2(f(6^vOAulD^iER6=&HuFNHHmd#Zg8&Vy-mVK z4DM$O`QhXI-slu6BkZs?M>4#(aZGln&*%J4*H?o#xXMtDT32kd4pi_2;vlJA(#2!G zNv4 zjUG6m(bY)kMvnY(40A`nx^`BdBml_f{lxO=N>@!3&wwW$>_!Tm{A^E!B+~SvA(Y|Y z^U%-jihCqfxxCgI;A73!!mlI)r8el$!Bdnn8FR}uJE`rp(7R(0h8$y&EWDfcUe{xW zA>AkHSNq5sd9jJ^ORwFbFz%-1QL3|sAvDtk2yj~rj5U6SH!fd4TU_7{@TjhH?H#%8 zqyd=hx4k6P8HGb1$QX9!XDa5pZwJuvGt;YT_rRv(@y6J#b zn$JFa&5(;WjV?ktpMY8e?b@Lq9b0C8S)_r`d)nld0tHn=V5OPk{@PaOx2 z@a-rY1N%UE>y-v;Xt||mPnKfH?_N1GT76pGH2w+(I}*K>w}_&k}IDQQ$8vt$aoyvF8#u9HMQ z1eA(@tz|cbeHN^YT;ZwcE1+Z-tvtTBN{}+k0;9R1Q!f1Lfb`IRW1kECahp%aD@Vi zT`y~1rofV^um_%^HjPea&=DnPz4vyc?#nlG{U=Jio;&B}>$-i^IA;W6H`2|Vw?*vF z9U&uxoUnqC8vqD4^k~BaeRg_Lh|Gwz*F0}bWN*>YS(li9gW;Iu=6USb4Q1PMsW!jk zP}uMd-_Ohg4Gy1mjwQBKj5QAp^z^Jnd&0C*lCRIdgfOsu*BMM;^|vk-(Ms$2NXad< zMZ6A;_rNNj^P#spKSy+*e717s$OF)M(0fQZcd9*)epLxchzMz|;dprC{<_=J=>^e8 z9y{fz@vepB3q;iPa@Vb<*_vF&^c4USOt&F+7YjS^-cXyfv$~eFxAohB_z% zVh`y!;FowcpXF=4`~ztG=B}#&oQH05PL%|iNdeQ9&P-oCseS8dw5?WceYn2&O$=Gw z_FwRSh4JVX{kql$nTF>LVP_NFWI@Y6O62^=soa3(^d{A=TakZLH%UL1fCr})wP#^S z#E^FJD>rCagX7bqj_MZc{{0I5I}Y){YRPM>SPAQ(5_ zDCUT0WY$Z)3wV8k!6;Z11o@8mLrlZ8A4I!1gi*)pDM386Ce2p!C z6;*NX5I=4CIp9kD!g9AR#b@sAPPPa7Nfo_KLy8^aR z9HMQK5M5TDlf)#Yx@qf{-^Nt&wK@E9ZDk!s$zse*Xs)FZ&+LSOVjZ9LN>>OfH^gkJ zJaDHS*BfwVknYKLx7{ETTyHV^Gu1YF+7Y+X)m4O}4d#O`_Y{HpQouUxI#70!ZeL0f zm;J*Ghki6pV zf$S&GLLj{C5VY^yh0pom*5&iA@Cac>RN6zF_WWJkugEp8^rf&1OtmO{Hj)DzLVzc0 zbD*yVv5U&0daw@UM1tBsrj;h9CG9T5TZzZ5HfTtL#z9zQ3>cF?8@IZZ-|ghCkM1bc z246vjml&5AoegmW5Bo=cW}Jjq&0F!H2w^Z@jO#+dxI@w;0F5M%rf6 zNLxLVeqAKkYig_P+gUbSZqa0JWKl8;AthWTdzMuOoi<-~2g#_J?Vr-Js%)a4jOxxDyb$vfrs@p`mȟKib-b74e~; z65x>;8tQNi`xqVDqH@UrWl-mDs|e`nas5M@)=esf5&!(#O>KWkqGnz#c@!M4vwo{H zEpSQ;?ij#ka+$s|5VBo#RLk-hzF--1_t`J6&3y0`F6VY6oq~j)=67u5Pu+qJrzC}S z&*(5Jqo6F5;Ye0l!DgE;Z*}ZPI5;Mq4@d{uPalip_LlLh7Pp*jZR5aBD@_1Q1a8iY zQUv9QP}Ga~lT^0;A}`@Kwn-5@13tPY4{!OD5~$9O0O`pd;Z#~P@?aWUpK>-YbfMU0 zDa{VwrD>to1tMsa%9Nl^zE5*8GUr7xMY#jtN=9*(?PR{4-A%gKPc(S#n7)g)^YXB( z;%xo{XCg3wa?w#aq3*L7%rGGq;qv+79B; z^2bfsk&}N)VeWkeVY$#_c{5u0`It6k=I(b&@%YU+X6aQO_s}ce1y(b zzy~o1n+XATL0TdvzmIZu)^FIBQKi)V0`lW?)ZQm+ljP4<9!o4oaX|&;V=o_ScA#x!^2sv-a{!uiL zUPWBa&5B!~nRBU>W9ra5UuT=jyYJ^^HdX?V@iw4y>@f+ta!Abxt_5qkd@|DB!wc__ zeAL%Ww1c$NxR^SUu2!yihpy~H40vpxr7rGV54T5=m|iH{ zgx|UsfQvS1Cd$DdU57}2E){k+uf+O|w;EU&F1(j*w@=F*STHcdu{!Y2;m=44#iqj2 zcOkv@Z^nQeA>PV8Mc&;JC72G0W9rMs6U5gVb$H{Nb$dzMq)CX3)c9IoEb(Xd-={6<40`<+hu~ikknBlA#}?s z2HCB4670H}r>8wV@w8_o#gb2HO&Ty+nC8%#5(kF5ie~ifa&BID5Uj5sn zvgs5_fgluYNcK`Kjtk&!PMu{HJYi3p$fgD;cF~L_I<;$eQ{B68S&X|r1t!t3y68@u z9uIoU?4VHk{2%tdGOEq4X}6^<6sKs57k64*iWDsl#e%yAcc)l!XmQu#1a~d&4hin= z?u3&*-+4cIAD;8?tn=rrm6es`o;BHfWZ!#c&s;aRw%eh^ynq>l)%HV42c7Kd9=oGQ zc{!R#c(ZXR*JWE^Xv)X*s=JxMI4O@VNnnt$*(J%n@9bqKTjWXjo>6$~wAsV5!Yg+j zSY$Tm04_!|XML94Fw=VN3T~`3dT7${uP;JtWRGq(;Wi#fO7d+@ndZie6u6-vPG3nN z_Jpg%Q;JvuwE=b8aJ|W)Nu*@DDs-FsfXFd=0kH}6D;`Z3Q3@2K(gzx)^JozY&@N_J3}AMYja9%@5L=)|d9bi}#&yh!d_2S;0$ovDUw zXQ`ewV5*A0ir?JV+H7;?eGTu)YymHFwMb{8rO2KZwEzv3rpV+=webj&PTe9X&YX=j z;n$mHA=bL&E18?;opd$JFQpSUUDm3?+lt>Qidsl?->ar~jO5C+$-FqS|Bmn)sod*F z`DNU-sW*ZDVym{*W4Xx7IE7aGAu3=;ow)IG9$D0ZRt-jF`hBd64r&MAd%BQ>h-(r?k-*;tMZ?3Z#qeeB1YoAspj&m?ki)jb*eb~eDJ(#yl!qm z-#OoA{^({(xzzdQ^c{sj?W90SN%7a5hx98NGnY`OfMmKgX}=7^y*n(xCj0kBi=GVajQnGD5bB| zK_>D({3WqgbJ6Xa?%@D<=XUlA(%YO|F3~+vYRgG>g1L5L9T4-?U z%0CMKec*?{EBe9mQDj!aVxeYXNEE^Y-SC<^!z3-K5f$yibIhM47w>{|6o|UL_&h;% zspF!I(R>k?EMvTTC2;+^M>gfd*34>&MSD)fX`^SauJm=A3pJh&uOet86&=+y3d8YH z`R9rLY&lwvuL1d+$NP1u!fsI%UN?AHO*f6{!XO1HBCj3(=N+|GSwfl~24NUZi1Fg= z(p-`H7xO_ON6M0t1i*I|G|wOTKYnpD{AvHN0b#nhG>{L+dY~@Q!wLVaLzpG$>0E7K zBMk0dWriasNetOadG~$8dC{*#Eewe7`BMXTjgB2F*WkvQI+SwQ@SLCmiKM9!qm*%= z?N=g%`}V#2m(?<0eF~24{#E6H{&c#4dZ^y%Z-N<17F_;{=WCDpIs)EObi@Rhp`_){ zJg!4sU%MSrHaXPMLeD!LOzv~`4a?h$o_9(KJhEfrg(?RD^GIgHGZ;s~sp2)YsAzf8(le|b98^oGZ&PI8vZu?E zCZO$`zBoFVh9SaBGeTI+D0V*AFt%S)Fm`pKUmO$${dj#2ZZWMiu5`B#7y8iR`pI{J z1zXB#?H;9xxnwa?BhEXgemX(xn{K%*o9G(hZD6*l;cJXhOmFFDVs0ys%WVdAQVb~J zX*6KJ)&-<-0u`OFB=*_Er*0yzj;}-`lkV)49^aoDvw3O2u9%o8mui#@#-ap#p3!zlh7OX|k?v_SW#$Yqz`VLYLt6kFZ z&q;ifFkKp({n>SH&}LX0i}m(lTdnUcU*QmUc}ZF*^VyxQ1#_dXvV%(d$8DOZu3fhg zn|pxQGej$Qf)*_fbn9lSqgWCzzhAcKE9GW(+DS7bBH*}3{Rr*3EFCq-LK=U+cMrH4<&mYkK)z z9O#aJYh21$d2ckH>3E$GIB1i7X=Axd{<;w3UIj9 zIm%~C@vgRK!7uXRbOpsCI$sX5#`&5v0&sCHieEm6_@m141qj))@_Q>fN0WA4e9r98 zG}Zi$ro z1a19~e)X%;yEK@>16yAejoU6|Qp;;r8&KOi>>cbZxlyHznVq$44~7uBdG79ewT@OQ zOY`s{ot?CDYvo4dCn;Wd>c{j9MC8R-{=h1V@WeAtXDOlb43~j{8(R(whO3j&&N4cY6#kvej8W`g3~gjL6$b@B|_*c?Pw;z*c#1uSVvCV zN_hfr*=d6vF)1g`BOiWP8ya~P?qcSjoT}$`{QC2>Hw%e&qGgWgBH?3Qky))MV{)cKo;i z>Rt4COr+?0JI}+6tHHXp7G6%a+jZWZexx4oR^0S?HCxJc=sV-W`5d@p+`VM&jY_VR zqf(sf<$~btc+&R7CUkMfR)iyg3j8w)v8D%HbfMb!YbVsHbOa(@GuFqy6ecxQw5KXr zE`Q~H9PDHZ@1oIT>(6PW-NT)WU*~?Pr)?Eo&BFUZk@ZzRtVwk^=BhuDDb}dwgApHb z0<`c>Qq7$FNEq4ZlmREe?D|xgfM>YaThsDNz@OsmBXiuhBLSa2=K5B>ISbDd=xw~{ z2dvNTgA>0s9`}NKS~Sbi1qjY?<4V&vPj9jy#jq{PCvihd*lF_!Lx)|*C-U}EesMO= zkvG;IEDB$NS0>u;mYteHvIj&+J^C#dD7Eqd5$~ph3iu$k$|%K%Z#5371$afTVfT zYoS584jy-2Gpsh0D>^mxg^b&Z`eYZYW|ZVL;oXqq7XGI4_E?Pun{~ubXSALHX8y>` zT0}!`s5h?Hw^v7xc;XR6MVYVes4VkJDN1Q*X}?pQ(fmxXXo=D7b0fr7x&h={wZnQ1 zJ4;ERl(_eMjGrERxLwxq1UeqB7D9K>=Obt2_{`!OB`@_E>155mMvw68?65m!gB3C- zLWuGuIN%p2N#vl1woSZO>44j|JD0}=SC>Qdk!33hhgBKE`AWILyGQcpsvAw3dq#5+ zsn_}!=H)@s_E?G+_ZRgi@GE!jO=p{X33s#fE@xA!$HN4rYv^(U!5ZvRRRFAA*Qx6$ zCxua2VbKW|Yp}f?V$p{@xJ=uzScA!&mxi0ab>_W+40c4*U4nf)#rnDu1+e`MWw%@q z08#Ad%jdILjWLfQv^NO$KWB=t?0BmxkiXH*2LCYC?)+MrA!?99FuDN1)&4Slj#czq z-b^R@$2OmRrhehI{E^Us4ey^Ug$Lft+Y!Rmpv+jm5gia6nt8fct8Vo|7h^u(p;P!P zfcp#DBVkPr1kQ^zKOA?8!wm6cQIqHsa9BCjb?a4XX>&D4Q^?~Ri2hB?&v6tilOa1a zp@kA1jabb9;mZ}q>xXAcT+oD zW%8kGXc|+m)I$rk`CHzA1m=Sx*Ke{%*Az0#jz2-0ZVZ~_TF zdv~9+2Dux3C$e^Z(W#rL%Jd7vIQtn?o;|s6;302hJ5tW&xjRwh@PgMdf&WOFFEQ(q zV<@jFyX)p}w@=)w5b!GdDINT4f^-%=g!#99cO7YRI$eBdQb5*(kfA#7L6E)~(_wd- zHHj$qbltl0dCL|=dpOh?Ta7mP;}$d+6CIo;ovUpdJKzXD;5(Q;jXJ3baO zO2pylD_WLp_9$r;S9D*H5c+1M(W9mJPUi8Q-@(WmOzLC%^3CF}>wNot-n?n#ogn9V z^5!BXTdnsxXQ`A6l<)HFH$+Ezt1ov5QDmdG(BfTsR4PSx?$+xKFsKA-dnxb=RUv*& zcaTeug$J9Vt)f$?Ek^OcgWAc*ZgjW)6!g7M399vv=$0NN%{@@Cs-jn4K5*DUu^{XW^hD#@jrgC)_k|U|bNCdA>T|t@P7CblQ&_+I%h(Hq0 zd4POFgR=np8sa>!t#4(pb=Si+f>aV3mAIXn8g(vbdC9sZ+@p0`{ z!R9j!s-0gQ-;*#}P49XYi$-sKx)~%XyN;Fv2`50Jg5*=`FL?T%5&Cp55es&%{Jx0eA<$juZ3)Kq?`A+VxdlAFj|SqmC+8B#5fi z&fuoEZi9tU@YsK4vo=$D)#Xz)A9_^Q-PWMIl->BHpQ`12re4}oS}ce)kBJu?$1>{K zqgWKK=0eL|m3klw+bts0p;%H>(G8wq==sXoo2NL}x_SnG|iR;Bp2y~M7Ji-j*}5flp|Jq8d65hlLsx@DqE~Tty>^T9oUrqfvQ|jq5x7uwMu#@7~pR)Cw z`k2md4==^972&+eoKJ>kuEkfQ&Q$oJ@C1D%jc;pKB>e2vs{k=WAbnF+{_>`|ts3cp zS+e;-{uy;wvj&LNlQwC2^L&TZbWA8qKDEk-ODAwxFadtxNgsq-7GJ z_{hXpy)3xgz00sch8+_h6RhqK=JifBa*WNcS`4Yi2}c;@hAvEF@a|5-dT{5Opy zb|2@UZ_SVb?zSHn&0V3g!TKUO+E{u2@q$Xed;wghObMgF8`l4gNx_8bBahJQ2_VmuGA{6IgTh4N=ZzImjs{9D-CI(cYD@?Yoz8vm~xz3yAfD(g*e?3 zU!(1}hS$Em_M}Uh%FTb9+s6uP?0ZuvUMphod>YoVT6f=_cc+8yru>nPCBN~ z*LpKxK4MCRmDLIYi%vF~U4^2otRy5K%-@ZG;n)!O4KlP_5`oZfns2C#+`reM;B|6{ z1{pe{2*eog#six~%IA?|ufOH2yzjN1(7db?w-_sKPrCo5$?&SuAo;yc1r8o3BA%-0 z)rl%Z?$P26LUg3moXOBhQIQDPVDPU#_2Le&lWYCXNFEBDR zUfmuuxHg}FP`Q^F9*kS8EMXb>Oe5;&^MwKF%4|~A#z_%aD;G^={5H#^ z!zmIy@lhC5RJrexIIMhM2fohRTCK8B1WMu{X;fSINJMo3O6eh452^!-BUvAxKXfKB zZ%b2!7-apNs7Af7!6E-peBmyh zuLeZg`AR|ZMTt>TT~lh&Ab%1b*G#RtCn4W5eBQuX=L>&dZhS{wy`4k0)tAUkbgwq` zjZy)ruln5OzAcx+k_D6$m(7{7uD}Y{y2lK9WWHN=-A!P87E`zzIc$yiGv>OX>V&2#b&hv;BB zA`FN1)}O!{AV0+AmGnUTDd#BQf2rHL(c>>Mn?v+c8tbW%G&p|JcI@EqgS;H~lu#xa zy5HvwCo^<%w?$2Xx*xHJ#{;Ulqn(Z>}mt`hoxucu5X#i*0+xqXc5K461hBJg&6w9 zQw(k6_UWNom)H%3z>y_^-*w;yD^{v~^RXHA^ibSaCZkm0g9YgVf{^Pe-Y zcC1QSM$)M+jR3Xqp8%@ErX&R(9y)cAT>u3YMFJq;Ju%pCkJF-avAIuPVM3!kn3TYd z?#25k6cN#id9?EGLU}D8_RI8AQP7chS zK_6m5>hj|}68U&D08zQ7tC-as*sLA+q21i)c%kAlVwf&W1Z^gj%gk0oJWM(v>S%>~ z_CJH7@CiO@Vpi9MB(zku@%%~H{Oxs-{w=g$fg6BhJ=q|)5T<+&q_S#LpY$!!thw0n z%r3_rj5B<<%T%0|(Qwy56*+oK1x=$E9j)`EgDV)=f%*kf6j@i;l1v@6;5wdJjy2WS zabNvrd|{2Lx}_1$byNR3Hi;InVAr~r757~^xQX|<1?&YOy%I9F zqy^R_3w{kMqw=NiL zT@kM5Y9Rp(6^I&7i!ZL>vM@pQy{~gUz;Ac`-GKapr{j174m4ck*?BZ9%V5e7@2^f$ zNMCNO1g`V95>1ZdPco!j-L+CwkS~5g5S)ScL*un~`7LsPFME4#X?sRZ=?N+_TT3Pd zzk&Gu_!qrM1XInLYOVHmuNPjY*yK@t32J?P@62m$OY z0w-R+5xL?pTPU3B;R~L^ag1TB46o~WkZ<1|`dhrOGGGNVrji!iaL&Av&ZNO?OU)Dj zD^-?vtC!vU%jiy#wULLt=2uh-qL!UvI*~eaZo4f-(RT9XO5Cx*IkQuvwX+c$Um*~# zQ2b%P75HG<>2Zqu@`!8+3x~o28aYRqMRHrr$FsJ;Za%ezFlHs+&ReGY--zo$ zlo__DV0)}>YY`!Dl8W2HyD}u-0LCl@s>7}v1-;kUwfYcDhQl6p@#t(*UrZV4EMMJn zb!2#iS*_%ph!97P#Pg|6D(s({TAA!-!Rd8MMIW}A+jRx4S{MeJvo6fl!ZtD}DEs!N zB^lldQ-17o#d4QtWvcx9o%PQzFf?jdXDg@<2(ik)vqFBetzKiQCz9yA`8Zc)d!@D1 z^LT%1(p@O0ij9LKF&^=W9HlT|8HT(VPLm(ZN!M9O$Hny;MEN;jjCWnGp2D&W*=*OB zo+*WFHeWeWJ;IEEM+PG+E;Q+&&Rsvt@KGj)pN;dK1$$b0NaWdKa-=oInzaHdBA>KL z=_rX&#)G8vw!UUMdtxw^0Bzi~2g3*7v~GSS$Y~4b;_GnL0^EFa%D0%9=KAbz>Y0Vh zg;qWIwF;s@nXFS-4GEQ%k!9WYJjpPr`r%Wa?kpOy)yLpF%fuiT{0U~#yx*_gr&7to zZ&Y!e7GL`(h5b_SdLz_jIiuW!94$hrGG@^U{n}Fs!$**u7p%>~^&_JwWY0iyGUwhl z3*T00#YN_6!3+lG$NAMCXe6Dy$}xG*utDKVQU4$PJAW6h3%Pu@Ab<`mlO!T!(7M24 z^9(HIWI*3Ce_P72N-dB^2A8=@fkTyTz56r!i(EVf5@u1E&eCFCfwutpeQd~{k(pXS zCqDKbU3FpfTYJh1*@f6CPo+H|8G7~Gu#hmel01-lm58CCKWlmLlxuaj;+_Z&)8p9^ zdMVFd6ReY&!ypK_Fx#oF6e@+w`<%~t*SKUtJTxvtDt@@z=u@UWwLyV-Jyy||d?$N# z0ZvW`%hd8PT9TcaYz74;!TvJ~YYL=sPI?vmfR}8Ilsdt#j*K$gEcoc=B$CGiX~ zA9?5g_?H+!FsO&$7E6U*5a(oaTyDX`Q9Bfg$Na#gi;j(+xq}2J42Ini0BgkT87PIW z6=ESc_NIH)!0|dA2#L6Gjl&9w>g`um`o9KzYk>Er2dBf@rY2X6i?hnr6E?RtlBfOS zXe_516CfYT?~!Bbyz2EO5|~w-C}qfgj4>#@Y}Sv?VMeZ0-nvCZ9aiM6T z1#<-E+Sr}!;$E7pYqG_t`CRYZ*4fBJ2vK6L1O7TV{M+hIA&=#QjO5>7|M~OtKX6-A z;RFVwLoX;IGzqC5kBQgZG!@t4?UK98Cc=7!j>*P8#sz%O zak3p7=0#aiI2WBT^j4ix7;&9nMfGND&d;8$>Hk;~lh&{9b*<__s$$l5^q%VfdY0N- zq}3Y(4Vls%O_UZnko;WMl(bH#s?{^|{wa_MpQ7+@a&VbW>Y%G(6T^gQ-;TgVD;7NW z0Va2D`1~HI+W@DFlz$sD#JbMBt8L(;Q;qA*>zBqGnLBY0G)uO<6j*%+81ysW$>oVL zDT2i)9?C+j)6@c)b)3y16|WP*`whp}sp?-*fiscPydwPRun~ZP(bZ4j7-zi4I#wf9 z`a(BpHXbg}d~6au_b% z95M2%EAq%Pjk6vcZjkn2iKF+mXzehZ(dmHpZ|a655tgu;lo4kmZ+u{6=qQT2ALBE1Gwkr zAbv#PmZ_ny$`%=1u<~P((`>(`J&Vk=X4aa*whMePXL~FkLP5!GsZZ**6bgJoZ2v-o zX8JCe`bvl|UmYv$3vaL@*(#AFcNh$yEz8q`x5{z?9;8t%6pA}ERwZE|A|gV{M)4Ac zTS=8JRA3myNXH-~YsJLE!WuqjmsDlHe~tJDj7&IC@u$-%#X>Oi=AfODCAYSl^qfTZ}BC{($hOHB3upWv?L5#>oO@=em#sQ&tkrvQ>+ zh{ZqRpFa^I{>R$FrV9f-COGcf8vSRP!M!j2NA{R7kZT$Yj^*f)%%>q2|3s&+gtT8g zt!&slN5B1<#Bb_!;Xf6+PrqP@-SAIuY+!1IA$Dg7PXAwq*`~ob#s7!F!ODu^rD34Y zFZgc=pG5unD?pbgU1$IM%J;8dP!nJ<*zg{w+z$UF0?Z7-Uf{os`0uj7{{X|cM!jCQ z-~LBI!wdoPRIcDZ4WXvJy*&i}lh^+NZ5*HNxjF{N_QXirKWUrI;g3Px;`~1OM+(zF z6z4lz%l~9@_&k3m^MJH`{f`uEe<*Ix?T`Oyx~QoziGKHbWpn?J6iI(%?s?1Y@((ii z`7R4nt8gnEm)Ad0z{|iW{P-UTKmCJ;2?|rgAj30to)ZfE6NMiYjN)^;7h2lW=w4qk zGXEI(Xz8A$W0BgN<+ivL^YvHV!+%z3P=?A-F$ik*ZKBX3C-8$|hAdVKn~ydRm+=Q95fVv6HJ zp9^Rt1Ny&h;7%fU$3NFmKKXjG`YlJWyqsq_BlAQK1xY_s2^lRwiE8Irrn&ylFf`jA zDg76Zb9X78X?CZ-h1pg-F84%-`S0`&suzK&M8nL$gMepnuSvfNHX&n>hF#$b-n63h`VSMXKypSUQYx@8B3F8Rv zBJf|CRcey^{VvQtGyy zSkB{hLLs_J(Panx)wzF3u%xW4vblL7Cgw1WsI1Tv-UPFMBE> zXtkmK^n#seY8qZf+S9i>ImTfLSxC;n?{S}WiZh$Z&{v3_P(IA`JZj)T#QOWZfUK2z ztYlO)9<@>$wM_14F<^IyWnm2SULB?-Z*0Endk@ht(nG=H^6E9g?k<@f+XG%CEj2y%vQ(L_ zjyjk|#@iw0^fJa2(xYl>_BO+cJDF|$H0r-O%}_UMvV(_084?pj*(7s(MJfHirojX*^ELWqgg-;qYLO) z+B^JcfzRACo_;$$>L*hwyHlz)@Dr-el}7>q;ZnlfOed>j%yL;{f+w}D0GBG8_UXoK zvPR4rSSyf)=xqJkirJ+~#6B<&eu=YnJR_VF9Ws8rt(%R-Qe~%6UNN7cvwosxuez6p z+|QOX+6Wcob#hz=cnekI#%S7Xtp+_aJg2lX=F4@@MFA2D-qnfaL@wk7CMCLbNfa$Z z^@oV!-~6;tKCw)y`Sd|=AcI>yN+;VD-Q^~XYjP1~vVyTFb|L4hRI7j}0lAyucOqWX zT#irtj2H~4b5?Q=3_7;)Az*gC&tWl{?hG!;@v)d*WP49qAsg*zA+dj7Gr4=U<$a%} zB$FH96$GVf(OxE(Xny7HL)~nrWJtrDypgrU_9kfN7qyi2M9k=%7;q{X57_^LGQ39I znnuSfzW<78a#Q>aXBWk^t@mgPXr|cKP$t5`|3S2muh!h$X?x$_|F@eQugww5&>Vr2 zQ1+B(66+=s<=kb1*j+ovzE&pUBd@Xs$x!%fV{n|nxRA}LME2Ke>h^JcoTn_;2lu5q z4yp8)!y*SMnn}dt1QndcT;&=|Q>b+K4OkGhcTm1`UH+KCVL?Re$}qU3u=3f=!PP52 zgIA(O?A)w<-|^<;SJx-s@@)#yzJ$1;DGiS*wCQFYS?;O5#UUi*v2CH6kzZ0m)>LU# z%MJ8upmLEp02HUk!eU>-(kp{3F{YG)oJ!TY_%9=g1v@v{F>!HO{#fj@+D*O2mQHB} z+d3+Y^b_lOR3a}A=lR||??#bnzT!ZYk^6d4)a7QnAbaF+#r~F1dSr^Pc7q<&h+5!f zT&{A!h09~rcT6ZlTMN0D0 z(Wd#t(-IBsIfm1Kn+_O)wnVeuF0`;lMzh=X{7RqLnvG_tz`=u*# z*fy}2!#2plAw3RHc5IsfckUO3f_Q30iLYMhNMh=*SSf7<2_>6R*>h#!K!iM;B1t3) z8vGSk+Yoi`t0l=mWfI4oVq2{Hw$I2=+WYioq7NQ`?fLB3!cZR0Dn&XEE^NZ{nmjGm z&uWVVSB^=QSY!9<)m zlFt4lcs%4DpgwUX^`o}Ta-_NH(vtF%860J(QiXAN1gzFDj__j`?NatDIY62)rBb;`jD0EFbVkl$6^qxRF#8S=Xa__!pdivs7uvbSAEU^ z^zelIajJ+45Q(a7Z zWpu;&zgsa$xpXUqntdEO@zihYOK?|ToL)vDugS@Bv4vSp+7{;&)uT(#aiZHzjeYB{WYpo2?B z4hdOU3~2%QG%z7bmJQs>p z8QM4;z>r$zzHph@(WR=gmn;YzNNAF%vu7ckqW06}=^f@>w_RZ1vCVcr*u7E}OtWw{ zNpi01C28tj+e!7EClE~!^{M;9bGeL-XDhVsvP=H*rN0|ajgq2xHCgu){pOaY^LG7W zFRjxhRp)bP(M8}V>?$Uj_UbBM%tb%?4ixId6@Yg}w<-}iz1-p@(fyB5iNWU~e3jOx z9XFW|%Jebb9iDdI+3)TUc^Zr37l@NT7)^>W*13ml2B3O7bz^ud5%FkIMiw+>QB|$1 z;m0yR{0!+APUbIVrxxTjFbh_}k)1q--89`rO{t8R0t1yDe(2s?oz&>csl<+@h)*zw$qs+l7Th;izN0Ll0xHxb+C{LrJd51{R)LU`8NWV@41~ znzjdt3vKPwfk$On4MvU$ctJIp~rq3yb|hTiA!U zJJ^=@Jw$Y0>`!BV6*u{ef3;4q%?Ys@QT=IO;wV#Gh=klAs(DfAHIbnj9{^WXNH^v? z_i)_Dr)UwC(CdNraHv~PL?N(eVaNBxBH)8YJ8Fk6g#2q`di^bI88-7gX7cn6Nl(GJ zApDeUxCZS>f<5vB-;x`{ecNuLLL#ZEM#P@++q-%~MP-;{%?MnqT=*XJ+sl*_?~e1 zXK*q|Rb+zO0-ToD*s=Tbg|X-(s>2!E-!w@d&h?V+w%sf}&0EGBy6cQf_2^t}t8+Pc zyfZfWwX-Bv_|RVD;x#{)dG@4yO;i6-XN;a0>etlLLV;%A|AG2W70s#2EP zlnr`QC#}%dOkZ_TebJAMODQa4OwCx(XY%NXjx3aWVX<-kUaw1bcyOwJ>1Z@b9IrsP z?!wKY3ZT8kpF6~hN5{C|BoMB zpFR>+z?X{0TF$Y!y*^d$JZ~xCaJs9rLH(ov^C)dLpSMpmpddUIs>AXf?%1Xm7;Bda zuBZM_7&XkiO{fLG9q-?B5j;6NG+2hAOjwm9@u}5OaC!gbYmBs15|bzYd^8i5V{qEu zB|m#|Tac0p%Og~ttyw%_tj}NaRKc#IX?Yqxl@)pBQ;9_?=;Gv+68_Yr1Os7thUv_r z$iXMaW#a_PC5#M5Rz8)5z}OyzUFCJS`04uOxQ1oFJzJT9wS_#X4x&E^q`(q>mZx$U z-+s>^Vvv5~6&MzKDj?1fhNY19N2kO$pBxt#FDy-Dveh&5q%a*!VONP7ZhN1~kNkfn z|NBkzUrJ8ROB9&OxJ4%zo@h^%D92a2=(bXZIDUv$ya4srmbPf~FD2G>9&uMAH~~l6 z3=ZHjpu$D1Biz&%2t(OfxkL5}8e`MVd@-#<$iuJx`=2Z~;c*Q;(`&x8U;;NK_n2KP zt4_Dt_P5?}@Kx#iT`ED+uK?J`l^CY-Hwzu?OwM&2#QVC>%Q;q0h~|HpRhpQ~N*EDn zWm-mED92VMSnD_@ibcKyjn!IT&-+PRW{<)b+|pGqs{qjjm?pM7A)rN%bWas=;N@+H zrTi$EY9<5E+k&`uM7662#J7bKVLxvj>0nK=A>dbGgY-Wv7lU$i_gQACQ|+b}yShCw zAXiISdnDGNuxK`K+%eL0_}5sHLK8FH&B!*WRQtm6rt4S}FFSkVN;AH7A@6GDLf65K zq}pjG_Q&+B@LZ3r&pk)-(eMFzQMuiUy<2x`NcC3bJZ>W+6|dSCnaQmMGXA4IclI&9 zDK#l2-`dP@?d*kQ27#+6|rqW{e+d}=UFwZ0v%Ne&SUC^pV(qA0Fl?Nz(Zp&d-u z3u_EWR_#L*`|U10iPv84U70NgjU}C0r<GMZYP$EXw*2;NziZY`B$LL)h4Io@%(a{p*W!j9-_=ade5KagxmLk{!wYb&R z98KrV-oo?l@0BQDnS0mw0O|?SS2VX1IG~0paffA7X?N$l5iOEc%UZXwepB@F2)A`& za|5;Ni>dNH)qVR44V(QfZObaDGghUNNE-_hVB9P-3Pr|K9Yi>+RG_b;ZmZUbM2p7*Zjp}P=UjV^r8I4 z*>7_y-5YcbNXeE(ivb!mrOpZau6}K9F+}&LAN` zz=3r->ZL{fL1T(rmF}dGAG_W9@3MwUC-bYHyCtfCMyU!8KyHY6o=gsn=k^EGAr$LS zkaad}pz{Zjb*`YDcKa~I!xIXP3HP6S>(Qaw|Kbtcz=aa ztA$?cL{zNGTh_Idsjc5c_FtQK*rzSAjETNzY5_}*0>waOHjAwOgN$}m-k1sLXB|>` zg)SkvjHNN~s4^dPS}c@X=yF< zK6{T_G4{r+>WYE7`H0~B+nNClt(pV${+e&HjyL2b4pc< z(%Er4k@2RxvC!Y57q@e4Mg?0$Ub-zIwTvh)@d>I`v*eoY43oGob7TGAtGM1|Y)SRFcyh~S?95M+XbR1V^ z>>)1>vVpzc;8`Lk*(?tPI1au*wY!;uko+3ffiNl~S6AR@368*clVdqy3bGM^mq8^C z?-+TYCoNrDZ{!Af4g-*Cz9UzAp1QRmli;AU)`XsvjVdQ?`(kSjxpdUmuCkh=rh7J_ z5r97Lnw?wcV?hn_MOUSHr2aVDH#s%?ae|*!A@nHY!nm=Iq%351qh+YkyZP|l7J3S& zr$q=-x^`)bAV$ee4Nn)UOHFQ*EPTqh$cYXvG8@dev0}9@b#6*>3n|knRjsVCXk3D6 z4@=Mf9nrVu>B9E#=Blnrd}v9fL-f?wa|!jbtdRU%eCbcz-akW*hENIT`Z;ES>EE{& zaiqzsSY(pD1z58z5w32`tE`+_RJ!VPP*bag&}C1SfW8M@n8(uynvmwhF_NGF< z6Ualj)LaQ^rS0O3fYbd_1{wn_`Fl1DLh1C3*b(cg%`L{dpGO{v3whkm#fY#Ih|@8XyTMeHX=%?tY-QwpT50RIx4H2B5(7Hjokc(;!3g8#nw0OT?P#hWj8{BaHac74cAq-!KD-{k-a zXE?Q>{t=kqnP|b^DtYYY!`;?~GDPP#*k7R?&GnQd-gNI{CU;NO%ef@^F}r@`{aUh7B_v$qB)c@Gx>1}5e@AjbHlO24F_tI&{*zJ zAi$NtdG+z}G8ih@F>VANptteLjvo$&HUytYSLtfJPN`~jsMhG&xv{Srgj4AnQD49v zf}GbQPf;ItaXO^_PBO8dL`2Iqy?vmcKRZNRx4b#%YI9Q5XrXvZIGDUQ+2ICq^~lsX zf-u?Ny(S-9S5vJ((&mt55N|l47hrqaeo!V82Gog(cBY!D$?y9ukno500A$ z7!oSx_>NA4?dKtMKm#dfF3V!=k;N5sG#)-1Nuzu~rNWZm=TFRck`5ez;eJF%Kby@fH zIMIq15xlY}Ue$lMuO3N%mA0G~n^kb7o?Lya?bQ0Ht)Oa`zUdlmQdJY~G*EV5sd?I*vjb=FIIRo`>(v6zR;q%JuJTyZe?svR8Q0JdGRP}KWheRw0JQMNi z?wGI#!yK~B59C~R_fFgJrqT}K5D{nK2wcMR_}RpbM7oC9d${5-G4)OQT>~cvz-AP; z2*`~J6CcGsUAOI!$D z7!Y|deK<5gDtq6mLi%*RD95VIIOTG&Ok(4_;#Jv^zt?D;8ZGg=>r-CC#C z)e88Pk|vAE%f8jX?lWRy-zxk7S^J+My-mrV1e1l%>O4O&u9D=Zp(1Jx=1Bd$1H66m zudNy*alFCnzz)T;sR5ah@0g2?>V=I$=xRqHj0m~)&E4N+HLzb>y<(bOYN?}!08=iS z3T=#~iPH+J22paHF1&xrl`&WCJP3D0($`%3IdY3qCMCn*SdtuaUQwpYjN0s#S6SU~ z$T+$)yc$Pup(xw{BA}yzrsW6utVU{l@T0d-9vq#xT~W@-DxHTmINwt3B$l#2Hhd_? zlWwlTi?4^!&dXcyaV;ntZH=gwzcNW#IgVL=U6x0tfb$vwsK;g4=+xJn)qrz#~2h1C+~QH|gtkNQ^R z<;fmS;B74Q+^C~T)rufLuz1V7KtsIzEZMNfDDg;suDM7<2es^SV};Vf@2THK`ToqHLksDxlD+d{IhGu^6JBGbNRXstWZfgjW-6=;!{Z3QR+JS#Rm$ z;$~Mkz949sb+KNhoxK>4BAl#Vy!AEsLi5yD-;9++(QViBusV*3R&lZ4gYvw>#J}Vm z0qvm=FdGS#ys$c&S}0`A(*|3qn->j#I0whnLfSx3?IylFvyT2mpOLBwaH!){Mpx3Q zU>H-PObqiaboKmPYv-c9YUJ|a>Im$QVDZ*ARFTWmeZCc?JYlk(#Ko$1DKsDU(cb^ReW3jIqQZhBl~sg-6DcJ zYN~Gf3uO31KrWx-C9FbyjQfi0(bMtve5`Fm?88LOYS9C_cNssQs)5*SHcm=vyt?}c znsxMw30tk#_p4Qa1o+5$;V5k}R(%7WOR;LbYs$w?!(CP*A0&(bY?lH1O+UkUZ|jS1I+(* zm2aPMb)w!&nVji#CBz*BP;mOrnsIQ#XxYA1ey2*R4O{)wqywhzc51k6PE1%=hl47hp-C2%mh1L-c zF!w*}(G~3c_dUBrZ;RDnH~WX)W4Inoc!ZED0|qYhooacJm61ZfgX4TtA-BNN}~Ol2zsfdac}7kAX%>$L!V~y9@vU z(?hd6H|0^Gwi5?ZimpjaA%>%$PoJjvOHVQ+=@6M_yaE7?J1;WKiLJ!s`IxHVcOAh; z#0E!}DNv^xF8A46v2#{LW#f3|CG_dxYTbr!^LCtfvUx+=pErw9v{}B&6SbP#U3>)| zua$pNX}F43nJb~!vUM*VEvO4B2~{vnpI6=+hB_a3L@Mda^vM_*i9Mwn_a!-PN#QI& z9fe9gqhL0VgU(8Gl@B1_HvyJpXixCHoe<`7eTc!mB(pC?gG&ONiOhMrwUg~YkA1}- zhf9CHUPYfj#RhZ<)-&$(>S`FKPSy8i-!wl*h^bne%R>wQx7%WoYkd3xF(0JUKGqAs<^CoU~qC?}G z$%vqG@y!k=;CCQteEO>-PZor2#0S(gTM*&WC!HMBpj)t%88JKfeoXGw*xJ-6@@+`O zsN#6!Ag2$iMR}q%XyDm75yR^&6+KfVO$O$fha$tn^=4WP4PqvTipaN4nEU0|V`jJ$ zl=EsnY0O*at~AYHcV`@V6Lh{XqFs>CXc#c!eT{BO#Y zfpS?qQ**O(Q8|1TCXW9Cu@ky!hBM$%ZrgA*@=-ETip~lWH$@yMyQY2b&Bm0=GE?(GGC`K9;Y&& zA#&qL{Fk$zWHI6g4`!^%?(bPsvja?FW$fFdxUIOKQWJfERD4QBi!$NsrG?3aR&VF* zcZynXl<4K@y|?Y1J9Co;vJYSIaMdlOOjwFRP3PlUlytnarA|&T{OQ$^>3WJ_zgHEw zT&WF^-bpXad&*hnxO;!x#MGTuC8-1riyBBjdL_gEeSECnSwu*rNCUvf9$bJ|p!hf! zNGx`ksf}pFzL1gYweh}u-yh(2(nH?{_M+LE=;`w0{i~q1FWJZ4IBxax@@gNQooL^9 zlu4RYW!IQQGvFewPSjW2y>M2WwSgUQKBh*>(zP6AX^zIKz8~DIud}hw>9cnNG)z6@ zprSMK5Q(72O}FV66TO7*1+)y{?%&JELsCCIX7UE zrF%}2B;;Xa%td|KuGYxBC2yqyLu9{nQNNsFeqOwBp?sSvSxIU}?V7V^y!Z?U@`Sg$ zAnat<7Rho$arydl&wLE1WDH+GuD!02=*-h;^d5*N#rOXdAbl;&ZU@x z^JHz_SfJkWcPamD(516%Gg4jQ9sMddw(mtbRQ6e|-D>VG%buvhsv>LhB9NxD&Jj+K z+zG`xbY$d3W{>6iXEqWbZ^yx;!?wK`?(OY*gIytjI==gH;7Hk6W(JofjCp3br^l#c z(K~q6SwcXpBi%G4e8h8+Jy_VbctlCs_S5K6**&PTd+&vht7b;0&DsL z7c-BF8@=vH@|=DLC_vvVWHpMYAIKIU8q}gj+bIOs=Pq1R^(tH7UFj3oPsE__R)XW* z;|AR#Qcw@hxP%Mr3wa`rwL2w1+rkKsgI5n7Gvq|Vo-Ao_?~IqbBb3J{kV-@bo(YxN zXrM%UA7A?IYK#>Op5=L@>&lQs!g{6ORlWlaowo^GB`#{TKJkDMUrf3f8i7-k?GX(D z@7b2Ce;TJF-NGM}4;ignQ52Pi<^X!m@1|x&4qKww4d@ z^(g<{fCZei*j8IBobX7}=FcfOn(o^?G`W3mtL>t;o__7s{CAxKF4v;h<-uDzejK*8 zV$Y@Ub{VIZw$CR^WVz8cS>EZ&EY@QP#*7R+eN7a#6F@~ZeoJj<5!x%ID{z;1Z7+?{ zk2<+7&t5X>uNt$OfCFK=bw6wTsv2WpNQ1t3&AxjsVQDLqf_K*^a;-tPDL)=tSMo_w zqynQ$GQt!l*;IzJA;iy>&4+MRLW7p<2uG!9CL?avfg~~=Cw1=~9pQQRa_1psfn?=lr<6oxRwPaCoxt5)&p3S{D+}Q zM6C5N2nTCwKp`bIoD>4>Uz2Y(yS``jXWM>d<2FS2A`C3;o!%aUjn~szq$;vQ>1m3O z8*MtX!)-nbDX82107Ba*H<6sefGjEQ*n!#m$`b}iRYY&iy=x|0=~UH`>*{eEHHEm!6e6%7L%>GZjUqJnnv!sP>U@3?D~vH1<|)-Pf=E;?XCw zo~T&hk74rQ2})u8l#{BcCx6&wR9}8$ZKDt)IG*0*o^v>nBr6=6lw$roco1>BF)XMf z1&Q%=ZN5y-d^E=sSrlt^ny|@=SH{2IfN5l(BcrNv=8Ak(nq{0|f*xLk02)S5MD)yA zOF$qGz64jVnp!UkCu_m*Ozk8vmM5w$>#3!fL zMVM2MT3a|_3MY}GD-#~cjDLsYxELz2 zYHL=v4ts@X-0Kwv>vE&&UobO&@apab@mp6{5=q3H;Bl3c1K{jjP{5jI^*ffvh1i$9 z*mci(7o%w|2_nlAL_|7%2j~>sDA7*YYuvSgu&V}tOk-sJz^wapfigP#;{E#vwy_+N zTQl;)-WJf_EN;E6zS7a_eI4fp!IfVbglxj;G|edULw}?Dt-f>?=utq`7O#NS`Ay&> z|D%;UW|X4sE!34qz>XBpk0mw{HukzJvI`6)XPdrWrg?UzS0buwt`<-o$_N$)1FUSt zw*V6kG8^@bu!<791qn}rgHU_{xgsW(gSWvvD6W5I+S%?T#H<%vm$;{VlomP&%0T2p z_oR$b1;B>G#;(ZBK|8~~A^CEzCRYfRVa`{&(Y0~BU=BXXs3$UUeI2ctG=`0i=Q9WyHchmFwGS%gkx7$ zk+}3&yU%=$X?S)6yl5?L=&*_i9xbaUi3Te(>lxkXUQAX2W3Sy#4V`I(%|C0?Ev~Uc ze)-&ZKAAW~&vzC78K|2g*V%dD;w<#fr&*u#R)#8(CXM40Ns~F#n{J$?HHhL3`_6D# zxsS?fFNq|T>buB*+|1K3_;%Cua-MDT>|tv0Oo`OjQS&bw~$h_s> z>>0)AFxqYcKrnb2^8`LM0-||W%!KZM&8tHR5rVC+nz_2f=RkW4AmEOE+5 z-^EfQ<4U)Aw1vT#`S~YeHJ%(3ayV>e)45Y@3R?{a;6a-h6W8$c^=K=X&^=$A-zeLW>i~`)GgP?gCUSbBgl4n-I9+Ok`Z8jALVbI9C3p~k z<;NujV(FI|nOKV6Ze)~jx=n+PM>{t(>;An%#e1FoS>SK5-jZfuo6bd?9WG!HK z`G>x~;%UruM1=WMjx83qijOHsW8odX#!vfTf@+Yg;K(<@)V0f`YXbMtK>IOSv$;1r z6g}Ko9yB-XK$-2KX=YxI;c;>Kb+hoS&vy3B-4V5G4YR}&->tR1tUO;$xvGx=1&oz~PP!9&f_h@bkP}gs`t4 z-GCiIu21IE92b7b@5w!ED8J;ilaQF!(JXafQ5`7zrYT$YM57{F0C=eA3KD_5vVZCK=%Qh$T=mWZgtaCu()%OY;D zff@JtE&dfWlYOhKF?E8fw>y&15zeu$A~F4YJ7&7fB-)6#=gw ztNkbC;}?6u^+be;N>mMNmG1jfnf?(k_IVl{w_kj&zm$cE2}Q^^V8W)Q#4$64a-x{n z=Sq6Hrn$EU*!xxVdv)&qqpR!3qc1i8A^Ibn$}s5Pjm>gNo__E6;qzDE>LMmb$Ir)v z!35q>gR#yww#a<*Uo>k$uXS0Tg>;5Ahutfoa^}&Xw|YStnfFQ z$X_tp$y078e%s~OS~_1#t}5(x!hebKudl}+%>4H648EfD5VnNdIr;y=p7`rwr>>|z ze=GC9-~Qv1D(|m&yQSWewcko}?n)u+{~z8zH2(i*?;k4pwS4~HU!1C`a^i}QRMaB? zj_mSXQu1Q_jMN4UK15W;>A$&#xm~A*qH4N~E^_}T-|BzPp7XQx7wbN;xbW5QRHYj8 z2c21ISN8hN-w}v^zl1*9bjD{k=;@P(|3T&YpRVaorV||R7(deZ+wS~VyBzTsEfXdz z{M)XF?C4a}ppRwO3V!>-XM*VbM+`dY!f(4?yYq|F`PlfK;omlrzl0ow(QTJMK>PJ? zyAHVYi&|M+_WjmxEh5H-P6%z4z4_?3T`Ro#MPq$x?0Dg?Vg6^tafH9b(8{dPbhL1` zLLNI6dUcl}iz9F$75d0qF)Ns6T{J?&1p{$QPqo`~bGnxkpCkqo-CY{*d49dpsIZcl zu-0g;Ip(r<3crqi%wz$wlG4hohMsZmpOAg}^oA`gVUpKmJslH}8^sy)y^ytd zvf=}Q8$@KoPkb+%#pSwx5@<2?sxfEInRtb2Sh780Je4(bxcKt&y+sAqzBS+Uz(A{_ z4cm!#@I!r%5ZqhkgOFDQ_`agCJW~9}*hgw?rFOl0Pu~n6wEPJGrCe`-ljX@;(qnJ_VD1&qc(EOA2ZRiBT}tbuL834rkiCHf@30j=d(Lc8ngfsKaShZW7?76eG&4;4ypoHniM*oi8ADnYDS#nEm88kF5`WFqhTg zmr4}MHE{t&%)Lwcm?U(409xKXq7+_F`2ilId2lg(DMKgE4108Y4zQhMW`{MIOwvM} z99Jc~-FKY=f!(pWtcThB9aYug<}DA?{9h-fzAJ=fm|%ZOLhe<6Zi@f$r-^-(eheYi z?Pq%GwUOS8dzN#TGt2n1K8S{xR@#c2oj=nbFELW}(qUYkwYUApu91sdQl-%+6}QHu zpq&TYd-raQhng0Ao4Z`?5~+C2^o*!ni)%aMBmMExXWeJxhwdgI)ES~^*fu~!2-9A7vuyO_Vb+yGtXhEca;UoBc6uona@eSB=3 zOpR+gx@n(EcAgqgd9qlp@4jKH=k}tKy=H^=79JiP>8-GSQust4m&9;z31-6{1X`@* z+9GL=k<*2H$=WYXyl3e#N@0N`dNiH2mZLt=Qz2L-uS2|s@i;TPzv+1i{z4v>DgyHr zmAd_G-~dU7L^g%Tb3_~2K>{W{eBhOl1J5uA%apfHop{AsiTO!!E$b!geQs)nN^Q`o0~u(G`E_Y z(?+w0{DaxN8yxx~uL2LTO~Om|vd7E{Wd(S7&H`g34XR;Kk0g1y>-KXI7=bY&C*TZU z5T^%ZX36pS-@%n%Hh8A|GuMnqx1OvmN}MNO*|wntF?^j<s=!whjLEFUaT zM8H%xrNc2n)K3ZagQzH0X`r)K9;XWaJ-U`HNvVRk0I2B66g4AKZ9Vp>3))_xz8}I5 zH+2*Y9GC<2=s`4(u!UVSuIrnDP1AmBjk>_%aW`nmi*O^0>W8vfH&(>LtN|VS?Gr~8 zf7bWJFhnv_8*~x(p#uX29ACq?rZJloZ6$N(9}R}wsI%ecdY#n=!YRA4C3upZkVsac znx4ia@fK$11eh8|@GNhe_&>vHhm;xHFPV}1QEn?DhOv49gVE@q;nQ0x zI~}m~;$e=x@ws)cgJe-KQLzXAwH{;)UX#FvnWvC!gJPQ~gy(Jhn{cDP2JMdmZ@FsHgx}=s?13Yctb6j%!%)_Q&w9<6B_F z2zBurozbt5f&Q8jS3ME$CQKT~rUtf?5S*KjoB7>LL|ts36f52KO@f=|k<2h%*C$4Q zzDR(0s%PjQ?tT0?rppCcvA3Rr)dL}7DEV@fxUkmg6j>f+N{&RMLLv?qZZSFgGi3gt z7U=z!!_m{gZ8$_MDAE(Cg*cKnhosAzrCP0?T$Neh=IK#XEPQj;sqBdkff+c8e{33Y z27geO+OUJIz3jNY2_~quDs7LoHBe5+grfr~QNT@88P9_{qnpKr?%z*g=FCucn>C6& z1jbM@QhSS&<@nhH!xS$bZ2OISW37-YY5ukvZUw2|*n^P|g@fBTio)8Yv}n`~9#6BN zcz)W%4W)J7`rR6Fvh_Ps;C2;($AWOC>-Im6OPMSYd$&{%A`)`$oo}AZ*7Sd1nM308 z!lRjN^kM#AAG|Wh5@J(UsTu;_$9tjS^C#~!ZzRY&NIUKv0|hzR z;@48j+7$(cpdMADOWJIi$wRKL_4Ngny=#RipMJqeUlY&ufC%^)D*#7eW~O9_J;vJJ z&-iR<^WPYN>iqqSasY-GxXlJM&_oM0a>NmH5al-!x4n@j^GZ_mp^MVid5Iqhry3gD zylKvwz;}fvIb;11dcdZ8YzE=^Ou;$$*JoKmWRwRX9b~E69Pf6AIsz>`k&U&w4t0`l~bqLpjh+D?ZD`k8M%q@u5JrNhi>O*^hbcGCEsiJxjHjR3 zmuT8QtIb{eNt-Pk`N_Vn%d?o_YF8aht+$}pPhUTXy%B#&I``2B&QU_u#l7)J@4oiW zmeJW{)YIO_kB4))xhHfaR!`@}dzp6+z6;-e~q-EVxY|xMS`I`BidSxhHTo-X|R(hD#D10Y%&W#9Kzs&m) zeE79u5fI8=3S4);I?9@}KlI#gt_d<2f&1h*t^xC}Ln|q1n3cX9n+Ydw z=wy%P{bU)#MRo#7tvR1|Kq@97iS3cxd;0^04kY~hMqS5ZJy!2cSwnm>kLMHC5{%8V zq+>Q~UZXB6fMVeQIrpkxzMfO|k1P9pgh7D37w-FzN3||I>t|%52=AXTW#bx;)pQ2 z;XGCIm@j1gd6~^&Q9^rYEYNo9QO_I%0i2L7MNaw$Zmg|l%dY{LhPz^}qnUv;>B(oa zJq*;XSG`T`6@x;`h9v3Mcj~c<#L-uf_CIfO&W3@PK9se!BzEloAOkTUX|2)Vs_#J# z+5^^I)0pMHj7P2hBag7)clfmX)NHix?m=+g50gv>rH#36n&)&j zXOHSaDSxzneZzy#uw^w-pSrZ{yr*1cj6@w4iQ%;Wh znnuqSz8n=(EzP(Gh>()+z030@vs9--G}b$5M3BM!sT+Cp2%rA3INw&~rfu`dEo<3N z1AUj$%t4c`a*ec8Lgj;t(+6`uIsW0B4Vp%D0?p1IWDlOV; z^%)?f8Vb#5dr7o9vd^bk1v_8JxGYx{*^Ju#8d%(yl|p z$9!Qix(3^_CW?miqS=DVHB9hK}7F?f8CcjkY$ zn-Ovs)(q6&EY*bHlKjW+`wI{C5}}9l>V|6Z{$s_{^%z0;73>S1WN%gfZ|(m2d9E%U z+-VY)i2a9%zmTG#j$f@f($(O9IJ3WC+lEhc97Ja2rtjYc{-ldnhKlK`LMEkt{fB-1HAdIDU#-EEw~D`) z%ZMJ%o3Z;|?zhU^vZS|?s|5UFehZal&>?uwr#9z*8#$c|ro(KWb9nXbzZUS{X2kU= z9dq*P)mi+#G6D3~Eok`ne>$4~n&hGNK(2&7 z1qflG*xyfI?JwA`f^_ZodAl-y=?Rnc;p=a;xMue2H8G)=E&c864*pt`{=HiEzg2R8 z=r7o>yyLsr?^S1%+b6FZ{~r&Yd8aBwaavGmE;xFd>@U32_$@K!rlxg_UFJ{s!gX$; zuGoJ)CqOPDi04WeP0>M-SCE_Pc~Ts>Q1pt0{;!*_i0$w4Y5sA;)6HidBhYUzoKu~z z|KnAMEm+2MMdW|Q19vFSwaN{tnXCG(DKiNH5kXS?HmUUft(W$NN zI#ioZv8eNV`X=g{EGoRu2>&OxYBCr%JZKG1oH|6|W^*B+yp?;`^xQQ8;zzrw$$`_8 z$!Sy~mRcmS&SHBI8Aec?hr#K=mnwWikfTEtq@nkZzbQN5Uc{b)s@yzJs;~+!XRJUo z@fEOj)v_yKf9fs;yY8|-S%A~r^r!}$=Qw{4JR?R`bukj$tELGl;rHvyD#~8ZbRkFo z_@1#RC3Zj^$G*E1Iw2N3IFUCADcFECJfukIG*h(NZb?h;=I&8ZbU%}5f*+Lz5)ZXR zlyH4W0^`wEiX?dDHkV9j9*j)bD7FLu{2)-I-EmkCC%Wuz>Y)lxOoyTC!U_Z0YBGZRlRM!Ej;c8NR?M@76;TrM;z}7QDAVy1FRuK6_Wy z$G1`ZGm1yZt#86B9iBS`RtYAEqGa&Qm!%gi)1`xLb`qWiazt;rq zT?||wc|_Y&p%u)`SQLS`o>+rdp25thbyO0yHsOirZtQ;=%B?@=+gZ<1m!6B#Be*+( z<^dx@Ibr$1=t@J1rhqx_J%8Jc##CT&q3d#Uv)63?rxBBWp?-;W1Ib?L)4? z0}BqgBAS(r3a1fi``)^h2^P=lJ({c9T3qx4w`RtH8reRhLA};*AyG1(VKx^5p%nDs zL7lI^z1r|oiva6rOLR2pGG9o!1y1%xDY3|{cQYeDT)k>C|EkV@n}qkDmoGLfe9*|4 zAx6($gIRp6Oa;L7;*j*)dnQ};`fyvS-?D&Ay3&FFoV*F5(mJ=_;32~A!q4u3g)WJc zkx{I8AQ*`YxG!z(z(g>{b;_>GvfK`&*t6V9fZV#od!L#E#alSR#Ch&&Q{F$3K6KG{ z!;QhfpS&fuYE9QpqfDJhzfasU($jf1`43v}rP&XLiESq>9JClF6d_ zXRSjIHa||hE@3BYf4wB9Z8~_HB20jKetv!&xHll1><9^&PV*XUxW?`SR=r}fmrtt>y9`8QeiA#_Qxhn6`9V=Z|xK5lYd$P{Ae;qrKb z=5-e(IASODFB|47?qkDrDhnMn8PBu9#GJ@iK3XSaQrg+U8!gclZBv8-p_BYQ(Sb|* zJu2Iij9g*nQA}(;Cwwycnp#|>2d;W>5rI93HHNthcq*0x_dmG%OC(Yh| zREN#Nb;i}q`FZR5a7VQtH>{7wvq>eHcgrXnws;(5cCxGicBBxxIg0VvM%IZ{uZ;_K zEGy7g(m@!JWm%QwLU?5`z?fGq7d~^YVYT<8;wlmg)+*C8-}xy4fLEF}c@f38I&8q> z=kOaD#S#{Y7khqwt4rOVqk->-JVv)z@l{t(cB;qBN~~mgt|94lz#1vdiq>;HyH%s9 zpd0IES%(zC5s8oAF|F_KTGpTF>{PF=9LKBJaHsK*zuY;jQ&4i4v)S!_xV?*ZO30~H z)NnMzJ;*_;wCe{;m~U+P*-H7tOL(gJOD}k^Jb@9EElY*EI#_kHO$(_2mCA24WmR^> zr6PVjS-Sp?h`=AhO$gb6WGTQ51NgQZeA|XozF*3J#1rM`7N4fXb!+U|z->~t8799=ITB`z)LcXsN_ezG=H+*W@_KQfTE`_7svLE_rV6=CTqQtea_0-)keK5 z1KjViXW@YpWV6JEorM;3>jE+}AdBo&jJG0xlb8%mjRjVYDoXbxEtZb}Xz9g~f7}I5 zS$q!aFVY*@`55k|hP)Xe;X}Vf8tGb+8Ut+VUba8}B~r^2n)hvqoINpQDZp;k!|)a^ z_QbjQEJ_kkqn-MY4Tsy4rcr)|LgAv|uvT(UQh8PT7qKOk_yJ##yEl?*aXqp0K?Af| zy>5$`$a*{bj$Pz=4vwe@HK78Vw?izK!uK-fj3OyjKGZ8stCKXWvR(n|;;XZPe;#KU zZt3haA}?VlH|tj$T8mSH=fI}2Q?%1fo?z)IjSPjRrzN)=77WQ<4`kg&l7IAetalc( zQQkCJ?%;|o17j%Rhe6esQ9d-C_-dqEh4&%#7BTVaQ;0n=U-LTdQM~>RU>y*o)MlNp zHZA)nLX*noiOobfkXx%gbbgjWCW@KiCE;8Tsl%?j15yq1TPm(w`Y!931$ciK3*CsW zP2k*y=7g{tDhIKQrvzB%c&vggmQ|b!h3~FEwH}#7pSyB)rY7?L8uQQVr!rHIKM?x3 zvVY+yLn+4%H468>z#H(q9rKh@z<9E{<;ahfJ9CTbGI5xQGp#hu=C~3N{Yn0~DnP3_ zIl_Ey2y3gn!t@6KzT#X&>zV^WQIq{|0$_G(Um&24hxIOlK2cGFY#8oWgYW_z9LIFZ zlI|Z5*T{Z?iL-&YEGWG%x!RPNvoKHOjK`Jtjx4bB=%fas1K4 zPX^}e}0R+_39hrBUJ{wxzp!PD>7Vt zd;0Vd1T#4M<3^h3+2ikjU^;Am^v|{uXZ_JGb^U;F46n<)qy(l!Vn0ECZWBAs(h-WE zlWXy73slk>$dJaP8`|~|o3|Q0KyBG!tF7M`^$sY?rq;KF&VA1`k(66=Z}v;?PW_2k zwbs{bn1A+AwGi?0a?td#c=9&>GN5FR_T>U<3b}gk%@m0Ue@K}F8cixMpr4-|{#YJe z3ie`o$T_7hp;quxgH8oQz49+3p>}6N2k_U&u7|$bb=Dt|=mIcBuQdl-djOgkddXpt z==&RYVT%lfe`twN$n3S7HK%1x;!h{eHwVuZ*=23UcZ;%|)59D0?^sBUrCID4v7lBM znNj{)Sl@4rSUX~eTY3>upsEefZ{@SyyI>l^3IyyXUF($Nk_$kz9(#-QuANibj*5oE z4*U*+(-djZ9@WB^$3>c<@d*j=0d-9<{JEi_3>3KrGcI_zF1(GC(U_ z0{LW&%F$p3al1dkhaqS;XXrrPMF6~lj;`Ld?(&%&AZ+%v0D}5Suk+PG_xdiqP|Do z#(Cl0Sup}6@z5#r6|!4Ky8BQG6p|KIHAi`#+jlLo!ghJ7${Omv)E$p?=^UnoQNP8O z%1qwZJ`T@Gtozujgvyr?_a9>QB|?~!gN}2l2B>{Wda5^}*S97H)-gy$0`?=Lwm$;1 z#D~FI{NnWlS@?fEd;lFf_=dlx*m^L{#)K(PN7}Px0TkPgWFXwi-QCYtkwZ}rC zVCNp0*6O1LLIWc$Y(T{+@IRE~*7O1dhD<||YhsQP|JrwrwXcYucp;wgl~oK~>k!=P ze|D9TVS#NLPJ2F4VO=i0Avs3N59gf6F2aN}JUGw*be%Dm^_1zSlH#@Wa*d5deWfL* zf!4DD*X{)k7$GpX;jF9O9NW?>SP|T{#VKl02uulG z1ibTVUnQG{cB*lS`s@X^F1T~;%j*w_oeJF=r&Y?LNh*C8`U!$x5dE`-v$H2`INxQ+ zZjIpB==rp(X4PZZL%(6TF1QZPRu8NhRVS1*yR94+Sq2p=7Hbl>ZFa_6N#-fxFui3j znp9*bRCllA{;vD%k<~4^OGBB>p0zI@^Du>0f@e5F#>4)~1%S%`uni&0UZznr_v4*v zz31Ll2F97XSvxmbSRAW`lyGA2?h3}&9m`{307|I$fF_8A&)Zx5>K z>orN#`_Xm~olz*?dA3iyIq?*m&VWr35i?r|zt2HW@+!Hy-gtU%tT2(0nGC&JS|GhZ zeRO$?q0DBdW(PB2jr5|PTf6VHhJrkPlB1?xA@IIodrvF9Udpl${i&@}Ej14l3ECbY zdXl+GcpN{AOm7FYLM_#Jt!cor$rXq8#03wu5wi=b6(|*1U37?v3OkHzDO9p$j(G@|wG;z?LT6L*s|hX{^RDlF;SxoBGuhY^Ydp zXQzI6o;ac0foy&~U=qdU4ka4^+}F5XCHvB<`@a7v(Qfe)SBYw|Sr25e*vMMI`sZjg z^$w{+j#8^y$z0eu8RLjdQSg02tYpj;q5W1ZICo~DY>&C3NEqHB?3oiG@PQEQX!M!S zo#3TZ()f2!9PkBMmY#dLX83rbHF}VQPsI8WtGA*)JBoeWZ_lo!K_<gXlbetQ`YH0SM0>TTzB)axQ9B_qlAkq~f?p3btlHcJ1CJ1ppOIeM zX*p)jSs?W$pP%n{GB%22tcaZ;+^{g=M@wH@Tqb;Iz~f+@%XW>LgLaw@zz0NE%4|k@ zo6Zb5a9s&d`>KV5%v(2HbK_}B-ONl<0ABcVgt&AN= zUWu0Evc1<0+C3SrqZ?#yPC!u8-88M@=AzN_6&bslsH2B>j!7R@dV-UJpaZrc#i?4- z)P-k)d18I;$4$sW#81iT_c!bs_1*K7Q?+nyqHGsD3r=kCCq{4Y$OGm`MHuvIa? zY|dyQudA;jt?MAsa4Zk+(dOiy(p2+^@r#W}biK)emqw=V+ zdyPx6|H* zAHEF^nBFRKDM&W)Xr8mCb$j%L&}*128&hVfH{vfVS#{0abUP@8iVm$)81`OYx}RHZ zvCmU94>5dKWZ{e|we^_jl3|UecuuAf+xgG9bZPPj+i#od*;?|D-x#tJ4?VUOD77Iz zL(*G2_v1m1Hl^=4cc5QL<0Q~j&2S$0NgqIEn8eZ(QXLhCt(YXk>n7D6xKI}2U0}!Z zARf1z%v%NOIQU#u3a7M3EGa3de<;=rwmv1f}e-KXSNUPY?9VAShR_0JWiab3Ciy!=6^;Q%~h?!A~U?&QEOd3PfH2 zwfs9~Z;$=laIa-dvAFz8Jc+?&SzvkWGUv^3To-X41_#%3E1?x8>|I@f=PF@wP z=Us9)ICunJoWRzhCR&pRPkcN=AV&et$V~Hee)oJmz2xi$bxM$SyL`6AB3K!UmU?{tDei`6m^lMv_eyD&X1%B za0TTYzdQkZ$>8DacGNBkrF^AwwQ1=`M@F@#yrTjiY5+I(szwxvVoeL*FCKpWDtFxbB+;R9& z(zSt5m%4!QOE@E(8#yPip99X$#LVKUj6tXvk|u8O-1Uhau;djVQ_KeZ8#DJ=X1G~k zqG_X%tmx1;u|;4{@MOz;+Wt*?!l^={Iib<>kN2(_mdiJKqK{rIdZVwlwjP&wib)V) zjM;A$ZS#@|ki$L8p5+AzO&g$Idln^cNnY%mQO-JiIh%^~u9xq&614NMd|TLF8Ny?| zHbS|+X7VWEETQ$Wnyjh4C6Du3^k!=l^d&1{8@0hIyFDW>hcFGDEEh+VxR~9_PaNyW zp{N6nf2qS4G`j=3wJQ~$;n=U`4BEI&M-<=>X8(|Z=QhaRR_~Jv7O7D|NZu4TB0tOb zSmqvI443=JVTkOi3qo7kD4Jp!c?jbe_YBSLMUTK>WW7=~Oh;vy#bn}+Ky?*FC?w(} zkMr`DaLrZkrt&IcL3*K}%p0hWpdZVwN!Qj-O~{fi-@K&14aDKdka?j@GD1b6)@c%L zGVon?_4GZa$14qSyLZ9CYcHDRpGN<{9Wu$jnjhT+OlBIRD#hqIhu888&#Xm|@4_%Vpx$jXe zR_A4#YKA%VTjuQ}qZ46>zCRJD{l@S+q(K7>l1I8EArQ8?D!CP$cR~GmO@)FOi1>#! zzLbn|p7!T?pX6-*j=o`OWWLW8gh47B%8{XvQAv1$(uceGLn5H&SXl-2nFeRA(gg8x zpBLWkGgjB!!J*9xKq7W7hJNBDv9h*M)_3H)x)3djG7Jk}ID<0Ery)FrmNu-)X*)e9 zmE?a)v5M1d7v@ig{rl1=qLjgx`-)YodvfJ0bUZ@`*DYY>krpTb+&fNUfO$6d5VmIA z2PbXGQ0>{avxsg}uiTw|7*%tHOz2bJ|O0%f1n3Lp7J}7RceD-Z2n( zLtU59qgmhEr=hZOQeNI&-^J#lDJ=t)s=Tc$n~2!3OZad#HJ>^V*V(X*EJ(7P^G8;M zzrTFjv3$$ZGhW_B%T-P8{`X;_X%6L>DjqlWaQ*E{S;70CG&Sa)I%a1YHqTZ2e+XV1 zu)ocrm^hD}B2;^$wXH#@0&mmdN<^1-;PFaI+<5RoWgbSu^-Bq1wJ_Z~BY#XWPru|$ zqkj`?7u9*0;yykY9ogv5$hd!q?388jsNZXUk7Tbiz9Cky^KvM#TR9+BwlnmKN71Cj zkB#6NpDIrG>Bc*%A(J17j2Ou`=M{VVPF*zm<~=(!-+6*Lq*0{fmX@QjwR2vE%oWMf z70G3bnWIQ=f0Z2Zr75S&q_}_sOfZ|SgwOr@9}^@FwH2qs@g46uh>$LOqGyRlR`eP` zR)2`rUN?e-OxgnK76?JXM0=QwOL}xA%+|V1aN~83O0liYp+U`AOShw@N= zz}7jq6C(>MbU?j2@%vtjE%@Z@#$9Du7Bq$QL?Q&E{6ujnQ6HQ90Xt(G8Exaw@dUJf zHv?F(_7-^yK6Tya=&|}ZD>cDK-;15XKXcE;?;ShES>W9jK|>ThT}7jS z{%z6xq?2e3zIK%`PTm1y5(pxCUzv^WKeQq|jQjLpn-lSaHN(;}59S+VWdd5N@NT=) zm!193mN$`47_>OKFwtZ#YzqSsd|)|Q9hqBK+xeP6;^fS~iVY;_{qpG(zB(<PWl^}VrdcXTuA-j$zv@=^eb zq0moHZ;%*3M?CG|>zv-m2?^FAp5UpsB|%(RcDJ03j($-mjF9m7s=enj1?Nr+4X2h} zJD=X}o(LjvSpPK5cmW+fC6*=qne*y&UYiioD(+JXUoE7_yCcxICR8Y^vRd#+ePj2% zm$Ue9R%q}Q$Ydgz4sbI?+_3WkgineO*)~6 zKxhI2N|hRVr1wtf2{)eSoZ~sjZ@uq&*Lv5zcdh5YuMU~nv)k-F^O-%+r444}*Fs|@ zArw%p&#rG@@V8#Ntp~$JnoScIbPnsXJFwrw3BPCI&=N3)X=PopbXiR z7sg7TGW<+d&Ox2n0@h8xRJGk%&OPiW0mhxkwY=Fj;^tOM%jq@FxA%ky4>e88OKw1Pv@ywH2DvQU4K~3UUBWh$yBdZF^I9R zTTR`ykz^v1o}+#r)-Z_zlizZ@+j!=&o3`%;fuylJ-4DqDsm2zy#SiDXf`*`D(aSKLS3H4_B$h`NrH)=_MD41y2Ke?E4J0q;U>q#ZE(GN}H>hA~_ zx|7m2zzS>SwwL?*&XEQRk@cwz0!7e{6_SvsM8yXfL!7npFF9aF=s{(!b zdXGJPcyG$A-$!;ge#c?;6}Ps#WEK|lIFBbBZ8V&WlhVGMvcl5y#wQq{J*_@#E1sVN zO=|;Q-w$H1HJ*s0#2<4bDfkMVFPX?n)pWINrmiX|M$Jxrau!O$W2?q-F|mMwR8TUZ z#4ZAShr!i5&ukSJo?3-QKV0T;)yY&NyJLyCck7VA1Q1~=*sUobB`+_aeW2eb6+Y%% zE*6Vi+_(l-7V6aKQg&hN{LI2;o0e(1s7iESJ9tzi)z;RLm0sd?^9G!a$36g3Ay>2R z)GmtZV1Sh!;B&l!ozC)|-d`KWDnNi#N?upXfX3*x;|!N%O$>r^8uwU)Ej00__B*I4 z5ayZ1%Rt|z@0jV?8;U*rbNmxJzZ(4(qdjr13baHI9m6)mSp}xgHu7R{QOK zAjjL|V*h$$r=;!&Jd5EBP8GC=NxN^4$DC3JXlTG{-`H4_9=nZ9g=u;WmV3tI(MqB= z0DpB$3{`8(cC&m9kHszEu(`kh%U?MgjAc$%@(xQFX{~vgeGm<3=~Sb zTBO~%dc7NAVhDl7gsT^Y+VzjgEqkXC7hRVX+t^Sef>g$L87_8@O4? zx996O?_+5j1?Kl!y)?Ay5$v5Qx;#3cgal|;Hlv71Y^v%YEZOnc4j(_$c3zf8>Z<~zntgz8;r!V`2}2FdH;PGz<%0Z2WK z_afZmpg><$vM*LiavljmUF$tc$uYlH7Ir2{vD@!P|I{PAEkK0SDOQ%BZ-zt?2auMY zG6wLOyBRgU`ci)4lk29>kkFHi0oj#Vvih=&cI!WL7SdX=30!>YU_uq)-MRzY4A}TH z8sy3loF?gIFV5L%_oUBKeBYUXV}j5|rzoF+FB`O=tPus6X+)x9NSx&kHY7Tn@46;I zt&zmq5RY(gj%k1&n`SPnNCF5v)##htA_#n?U zd3i~Zy^XW=)_9q)=>Y3jb&byXUPM7fDu>tF2Aj|7 zbt3o99L`GCk~m~^jO%C2)t?oSdn7iqv}LMcw98<{2ilC7%c)myFM%!AVufY1IEn;q zaZw)R^(nbYL3EBs6H`GUK+ReaclP51WJPgJJCo! zXnC1-%?QqAUEIo~o0V?wJ5BdNr{8j?9*^zwlCQv!l-3jh?h=0f@*=zH9OK_P;FGYS zae09nifi+WXUvq$cM_^d#eHb6g4SA@A`7|=BVqwwpJ&D9N~fH;a0x9#XAtP z#`-Pl^(a1?U?0&4%yx@krmjg3tvDItpixR12G^1J-A^Ob=Wxnp#xb3E$)O%z{cLxk zTX}P;UIyFZ^i8w6qe$Bua;0<4A{(ih~tWs(S#hNjA6>br3|>xI;66__;(eMtb%4&Fpr!~CY9M|YRm zoS~+l&eY4o_978z-7-LJP=INQeQO%eS%^`P#`i7Acro$DUWqMmpZBcn;B$w-C}Q1e z8QXtc{DgH(VA2atdA!#R82VJt_V^%)n+R&j6Jfn8!|JVOc@j!Xjw&n6KT$YZIuRV{ z!INw(D6X)93dE1ECca!;3h^wjG#`BkjR|K#h6FSoYL(VRQPGCYEz8 z4`BMkHSDi=;ZvU_Y`pCrJLp@Q##D*!Ow1gxI7Df1ET1S|g#5Hse)OzFUETzxC^bYP1E#c~oLG+Ym`4y^r8}D}GJfBizw(YH_ zGm&T zPt`Yj14NEm6Hty^lXcwoILVfzC0iHOR<*skmzGdbcWvK;H&y~_Gbs(uBfPOO4wc_* zI4O?Pbnyx#*NH#@9rDR%f+<+G(&R-4=HrQXuwI(p8-!j$T_aSWz1AJ6Gc)pnylpgt z>EJdAF>a)nUB3}gZ5EWT{-s~)@DtkW3B5L%=mWKD-u24Q;=sI+rvjm{hv)cgAM{W9%dJOh}|SHMV4^b zS`>!ke|^V4tsSaW!^S;k;JNi-f1`_FO8cl1y-1tFJ$*byHc?JeR`6ZT5(ETFe=nr) zHjG2>^o|c9M7{$|e48ZmGup;pg*u0tTTTEs{56yKxGIILZ+WcsGTg=2WQUTR(Y*GS zBhfc~fL&C#UtEV0+6$MR?(abQEID5nOriV}Gs%yI*)1XP>=NY?DpYUflDWTHkLtKL z)$(XF_O?^-Q~#4~c7-v3(d@q^AWvPpCLG>u39Dd%tMP2wIlZE1 zIxMWlsLmQo`f{Ska)M;NaBS(5dX+JB2=96+5y&OMHh1LK15@D1{yZZhu$p1S>uW4D zwhNo1>oZ4PNW6U!qvqng$tUtSh5C)y;oR)?5{uOcU46WhJ~pZ7c!wsE%k)QlqP@pwD@5yxP`pYGiUiltLr4LjLJ4&_y;-1fc6 zLHboFkE1cQq=pRJ+N`Nbvg%TdcG(o$qly+X-BE~VBzawMa^%(*cp}A5==NW@S}|t~ z;94WaBNX-r;Ck@YW%AQb4*pNJ)*0_wGAz5O-j2%~lu9-{wBY{xH-91emV< zfq3;bX8M8U*Iw?`@y`+vzKM(q2^Fv4FGR=A7mfL2crgeDPOky3jqJD(=5ObOfmBES zPj6@C4P#mhoevZ*emg7T=i6C*|I^!9LqFfnf^3K||8=DI7c>5Y&FTC3c9!7(^mdjO z;X^g#m~ErOE7g+w$in+rl`sig}#dO2Shosw$gvXum5IqyLx&D9)2VTp8DUg z^%>1J>DKH$L{->s#L#of{(cQZzF0;^GJm^yXN-Eny z>CQhS`iliaG8pb4S2(OLdYkZ#ST^ReL6M3a!QWH)=P>CW7~U1>p(KFki2QSbQNdue zV>_e_e~tE!FBJ|<>ri21-o-fhf9u>isI~73Jw_uvkmQgHYmKBUVeSp6F*5{Q2>n;6 z$G+j<=t!bo!mNBTfS)vv^)eSei%gWmKWF>*-Ict+pW0}ct7v*5_MG`AM@^-ah%e^1 z0^PRT;86=(lG9nH``G)6O*fqgz~9RA4+hbZx?%w-AFgh1)N@yAc1i=s?XQx;e*Bne zdcX{sVaO~kDq@A$BG4~%5&;)opBS|B^|Af>{R)|R;o7BX`@2T37YvAeko_0wi*FWL zb)_aDxc8gLibDvwoetL9R*nwi3+G3gNAYw1lA;QP7q-j2!=USLHup$etQ7x${}_M2 z4&{D5vN}}E66>g=qf4Rfn5SdngYua8?UA$+UA3MSRRD%_IGM>G1RVWRy)FH?GKKHX zA1b-dn=hp-ru7Luc_JxzU-llptHNyPfJR45G&sQu*tHW$yk<@^R&^y*s@; z<}V3}>Z<(_^)l`{9^@T-7Lm@EyUmeJD?OP~k2%Tuc-;%8CN$}C5GzE<6 zF$lm^G$?)^pe|)Cq~aRBrc>RrVG8V0@vf?DZ!L}vdFpIJ;$o}3aM|;N%_JqV?!j`c zbfNNKqKcjQ3))H=yNcqKzG^=Phu^)yE%JAZkL9+jBtdl`Jeq)u@OW}gB zlu;ILdn-nbTkEBFuwEsw^jDgoc#&n744nx)vANVOzV%<@SqEHhp0l`PU(RtvHEFMW zMfMo+t>fvAdRS1Y$8fx!U8(M7#>ynGq7a+dWIC|+h8T72fzq%?z9s60JoRYAV8qIh zVZ~sT)ZlK!r%h(CoFYJ}DPW@8ryH9Al3aAj4lN0}Jx0(=0Bh&~Mgf_VVI9kMQjVRC)m- zZpd3@k|7V6LH27Tx`(V_0Ro3Qg7F@(_n2NN) zW98%k;E`i5QZR50)CH8>h)ygR9}OR@yaQ;}mv6cT7akVKbzaJm1Wy!J%&F-iYMyiy zM(bNeAUo@Z_O-rss|&BzMhv@xQE%+&WMtyTSNlgR<@#5SSSq{wZMB_X3ibE(WV|&^ zCwVPWZ(QpovmRI(P0*^J^v+ClRcoADZx+QvA8B^7Eu|W^R1@A9`ds9RT+eAU9H0X0 z)kzBA>^piY0i1=NNF;J4#mq_ZD%8&5b|i1Z&{^Iqu2DF6BsiVAsCkp_udMFALoD$YKV(JKBBQgf z3E9px>t^_K?d?R%2g+M~x6HGteae06bZ~<*Rj~f+mI_!Wqp~K&d6w;YtdY5CmzO>* z7?Vz@GfX}+s;yi!$gAdI89XfV9PA_+ds}h?CD&$dYcX>QoQe*1X6DzEl%T*uv23wk#Fk$Q)g}T&0cY`P`00E0>$7SDN;LZ# z92sKN85lnBVhVIyqf+gTdW1pfMJw0s1D_`!&BmdGdy=ck9ktJb&Rp{tgz>1+Na$2)V4C2@T&yqe5Db-4`n&k){y^r>C}X zz-XH_WMfR1i3~fm%GBI^6$3U6-We1J%gGN!BvT)Ij533#s%2`B^6>cwfq9<2Plo8q z;u2ki<&jWUm9`Bm2)}t=G3^r_^Fajgc`#JVWqf(X+oN2rAU@9@60N%US*Wq-?Qotb79jg(Dl7S@DMVbo%M1xswa2JE@fe5xF(kMaxvC84QLxpPNruK*7o)Y zZE*C~Pk~nztFexz`-hL`%frp$*b?&U>IAKH_|%2=aR*@o0xKg0334*P%(xVx!dc6v zYp{?(Cc~j1kJZB0^t{3^;b#_MxLV`KE&>viam9Uskkwd^sT#qdxM8Ux*Qgy8{l$IC zg6Ze%ioI%h5Q9-OV7IU)2v(^SPbg?9GxluV#z1^PyRk53Sq5^TV65vgKx75sk)>=9 zmYU>P(z)lK+!~D>rXsYWhYn@u4L5Dj#4eW$>Dio=a=yZ{cRXIum z>(SDEJoUzVm_yguV3G^?RVQn0LD)IaR4moO1CIw_xnDbM+3Bl7ROe6%OX*Wgfu$76 z<Gd&aW!8u~s$}pwVs03)JUR4*YStYK`Tdcz7DO&}A%ciW@ zsvaLtN?UnH6xUjY9gluWDbOx|#&^OO(Y?!?4ptT8kx#eGmPz z*VILxs*7pCzr@nV^cG#NMImyje`-R(X zWTr{t8al;4n9}|cRd2=|?vi~*L=@;~5*cJT_!)#De zBRmdc4o)WS${{RXzA3?pPS%*7zR$xOry({(gI~LSpnS@<_2@t)3LXW2-0;B+S0Bix zy;>r~l3dl}X-1vpo3#?G3GZuEuB z3#_=gT$v}wzBQ7XL9&n}zIAQW^KtaRr0h;$!lTsTp1`20@1wa4%#P1*Qua)W-POw- zWaqrbllk$!>yzQ4gO1ug7|T%isyrdLo+o(!DH6s--3SyYw9cT|)XS{uK6^pyc3WPF z4o>7#C8ArW6<-A@s`}DqW&S+kN@(^Tb@*W40(Dr!XQ@on?BkNVCGU(7r;E})!bc1b zDWr`o!mNXzjy_ltIuK+jl%s^(?z4~D?%9nl8QKEA!{Uo+VzS9a^suCFB;APoj~78dRRXB)$ouj*z@1KyGp4C9Ya z!!xYACtid0!~^4{G)wg8J}M^Ek9o(jimjRgA8D43IGbJRTta<_?^`WKrO5d2K3mW@ zQ_b^XQ8J7;U)&%)BQ25TKkSBI5L(aG{*VO` zI(*_K(q(b-BP@li-60@84xsu5%xu_2v_K9f?`qWpk{s?!qI1Aw$|fIe=x%{JL=EQS zdAw@E1nIRDx*+U`1#6x12ZuXdP=}jfAp6^auSr3VWp3(2ah|dImgM713RcM}+Vt>( zOOMv9JDM}Ky}v{#psd@zWwys0F}|dP!nhL2dY&&*(_V83kVpDN5sy)Mc0POlL3gma zYG@p*h%J%Ia)d?4;jU{D^=&udSVghJe1Zer!>}1wtg-n=g50?gygDKdfbUh|^^f4U zjG;f=KR#B>t=anux=k{6JYSm{rt|63=g`5EUf5#~yYZ?XtnCeh@o7Ez4RZ-+t-LZq z?;t+UOu5w?$b(dodnn4{JFe%`N&Xxx^!Svq$A=XKw@HPEO)~G3+1&I&xquJA>z zG+RRP7dj8$X9>GY#dXg^VReG;VCBdU2Nnk7?;MIIgoPXiN7$Z4)$1m)@sAuP_Z|DD z5hpZC0(9OywobTX?RjWlTBN||Npeadp_e@e(tbT#`4Fs;mOT{5K9cFYRJ7L3Ycd+) zGV1Pfvj|c+5DPOk=o@TX`~lYOPn|-sz!K`J}$%SP9TKdhE}s(y(Y*GFg87DHD~1$pWVm zpqjxDtJP#hUT%bZewc-f_rjuw;j=`7wda00`&tdhMrVtKU&VRl=dnj)5(-krWT3i} zja|nQ$=`I(C&A3D3bTuJ6HvnhvZ9IfE;j8-7NPXID|pEDVODB65!vvl)4S7tsfvqq zT?pe)3a?_-Bo{`z!*pWoa%6WP5$|Sl>`}Mbx`&G!xC#c;)he!zxq`gH>3cPWG4+7Zp$sv~`0oBs2aRzuI!{gF+#xH>KAktROC}56Q~$Ld130r?-ZWj@; zfUuJo9wj%_ePztkk;dkmRz|Egae?0Ym1DC}ELoIYR6}VEDY@793y@$AW2tdKLvsBq z03WblkJ39CME5e`ZedIrGF_`unh2K?h%=i|L1xjymoR2fl08Xg-woj$7UC@$3IyX= z4KYjLG4FX4n3izv>X(UA!p#^RPxNlT)hDF9^~xrHFxn5yQL<^Jnl2|RFKhye$p-@Z zi#DzD={%uvy&n2$#Sq_?Dx+P~2Oi7YQ7)gdf|BGo7H%6Y$AhA`4KVH zN@9$8eh8fFkFZf1BOln?jBHTwIKH1WfO$q~yjnq@O((~cg^y{`PJGMUEk$#adzFky zPj`jaQYizC)E8b(lN(sL66Ex?V?5Tiyk}E|e>2OcD`!t0VzGOfx?Ie0fB&hoC}N>} zFYVgof~{8GawxB7`>nO{?6%2}9tq7gJDPJlRbOf@Ig-+35l^L-y<*{82#`UPw~+~y zzQj}NQRhvlyNRivf)|OmY0v`;- z7#1P|)pNmVnKr`5mOm2MMa%thQwN?!lbbQ23VZ7bxGl!yWJyezJ6Q)BUR6q{a`|0; zYFd=kyKL}Z;G3YExh^!NFxmJiHnUH$t$~Y zu%U>)m&9VfL4XwUOqZOp%YKALoW${1?cOgwC@}Rcdk7IJjPDj2Z5l5FE>mR(s25ZT z?2sL&jt`c(n%7{reqNw=d7U@=yw!wVHX82lykF3cLtR<(tR#1MxQ!dUujiWKcVCat zGcnoN@c>7k(DWdsyG+AZkVkIa7{pM&i)LLFIw8>I>QlQ+BVtwE-C#NI6-u%=*)KuVfkxxO4p`4i}GS{_0hhCyv2!)>TJ>Kshf_Q{C?|K4dbxn$v%YcT-EaO{=gGaelyW*05s20@ewaDBL~u7*=<^wGh%l< zcVA-b@7>+M3VBFhfAzJyTUdvQK34J7&KJJQgAPtpDn;Scj*bqcll}EbZPVQfN7gM1 zN5V&V(dK*E)XFoT?zoIR^|pyf*oTL3W^cD^@LPG zE|qd&^mF*$31~x#!Y-6(G(KbI3ly3#X3hIQ-~CyG1{BRTkG>G zeJrY#KD+BkO@-Rzw9B5d^CP_~qb1Q^^CskOqO-Tb58BV|kblYjeAyG>T^?EyURR|= z=|+{w9IJ((P}Ru9`Pi{WN2roL0{@BZxlt6vR&D4S)j{Zid1A1wA;JY<=O8^;RA5)r zUWh{DuvO1>`!0#H&+{^kF8CG|C+NivyEYwh$=nmXT+1@-dOKf3;)JhHFU=Hv3Ja}y zV|s+AX;(Vo&#dJ9Ta-#yAm%<$A|V`{^3TojUx!+xw3zMa*(_R1oC`PHIWcDxVZq_i z=VPxwpQE{*!*pS~Y4MS|MCv`Jk!@RuOWKKJ3$OD*4D=WD;d#9m{l zGB%ohcs@M%gN_+YH5@~)y$9ewwe8=d(>=ma#aU*5! zNBFP)yURb5!$VR!u{*S=S1cEELkdIHYwP5CGXs%WH_gc|C!%^#rscwlm1t{zf9)8*85L$diP)J z{pAt=>zx0&c6|9i*EwfSoGSfQ3*f)&@PC%&|61}tmc0K*OKztZ8>td^cpdvc#9E~I z1h2=-rP}ZJ#Jx{S@;uad;A0W%W1yHgyl6tZDx-LD2}^sXAAbIkuAA8z-CAl^ClN9j z1Qg))#ZVSH1xu`U(|7im4KKe711m8MBIO1Pq|$*vXu&w4vqnVzLJ*XKF3ybz#nwof zH(OV1iJRTWK2~hr;qf=R5J>UP)|Z!vVvOo-y|X)gueciqvO$7@+!JBr&7RzrUTww# zwh2==(7Ky^}5FYzYsqamB6YI!~hi^*kFakUB?^ zjcQKAKLqg~=c*u!%`OZMKnpR{_5(b1xbPnUCJWU|evUwAgWccXKa<18js08jX%%s) z@D4n=At(E{9)CviF_^ei!|yHig^hz$m~faUx5Sd^pFZtxUr&#TE#v46FRtat^AZ!% zb}s|8LViWEzrMt-VtS^3HF9wT-;H^bNW<|sG49-+#h;9LhUxk04VS;^_$TcOju@hb z|2y6P@Z`VJ{iP)TRpwvjcM0qNO51(KTDEv+gWuY;S4KuCP(9t^pHcX)?1cY@?<^Ue zQ+^0JSkLXD^Q;DTM4=e4Hj&VXA;v-VK*wD>Wrz631&CJ6u^bijl3|Aq7ha(TLOI0< z3v&&zqAilPB;$EdfniIapwrTO0s`UyTM|q`Mbv(*&tt?s`BM7i!u-5@FTN8QIZ*dUzkW|CqI=4s)f!5xJXQ)gtF|y5 z38(`|h>*M2`G{(be&{_qc+k1MdD1H}b=+%z5sFtq7`vd0)HrSRY|2|Eo`f=^0_MEy z8tYN(^v$T=xLy5-ZTdB82~J{RP%XKLGJ~~!z33-HC7MInUg?{$)K-5df>$%nl za?9+yS|RpT6Ss#`JnTCRam=+Va|LyB$F&`S?Wg_O|*qJwnk282E^@s^$s zJWlm^CM9?6xUd;6zvPyJ-r9QQ9GOFd=AEwXnGqs@7ardJ0c-T49SquWeu zwU&FBhwdFk8#A{?Hi^`d+MI_lHI{XGAJ+-F<-+F$8+FT9c&&@gfX{k~_;rCwYlm^d z$nQQI>X9yJo>Su+PP5h99vf31R=)T9uxr50fD=glL0X%&<=b(Ot&7meX7Gw)QEIoK zPP(V)ar_3GUYgO+?7a)DPi*LVUex7gj>eDq%e1mA%9h8K`3~)>M_{-{3L>Xiy}NFW zmF**^u5zwC-0$`(~&^|MVpr^T-}1T^j%N$Q`LTbPvBs*CJ~^@5s2hn|<= zBKB{^3Q~;}4iPQ@7WSY#mVtw_FFCAUBNj6Jv8Isb8p4aLx+P+t=hCXQQffOJ(1rr#B>omPi+~D-? ztn|w|qEKqzz@!ykhk4h>gF`$h>snL&ZX7xzJ*m>^v>vwDdNi#p6y~nvQv=DxAz59? zEc9XSK9o7E(b$*+9!ndScrqGkILM=rp487JOjld%TlPNT5D`KnDEJ?1J~8Wpip@B# zkcJsqb${`6Zm(#%v^aNwR#)EiQjCnObf9n<_{d2ei(Xi1zF&P&Rec3|oC51NkBuh< z>-Se!VB0xKGN0@BJ36(}%8I|B3mURk<#Pb12fP-e9rTGpC?;8%in=<5(o(~ghb71E zNjc>z#REU4q)1j0)mSPnnPMlSayn7h zwtIZ&)sc^$cVe)ezt>K1bu_P>a(rsxw0Smj(=$sZpy0~=10J_e8xs&MpT?D- zL=*AmAMbVZZBPd3rEaS6zzNIC&nU5U&Qv(WET(Hlpl#V{Fni=$e_Ew^;^@=BCUCLf z-n#xunKP#M*|EH>Hyd(c&EEP6j*8^fr&x-5doqgGnzxVg`czQ%uR-BT z)oO{5(9;Za_@Uv8@iYS#TqvR0#yn7y!?x0P%wt}6lJm|8A>R6$LhUdQ{3tXAl2kI*>-nLyiJjKceU zUXuccPPVU{NRpJdYaDYenm>`mG zu7!=i*oBs+m2=nMs2T&N2o}hO;H)Wm6v*bLQh)$`WZ1kV{VLE^h$lB>(?oZ;?1Su! z5uGa~XZg5f!YaN*Y0DAj&k8AXg^O#F@K!Sys_djHY+&2ll0w)BP9s1nUg(9#rTf%Y6T~a-6C6ZB0ZI>FD z#ymp+886c@Rpc+N{`G~qbQ7EE|M{k$+_(`PZrnP-bR$BYr= zlf{I6?$@MCL?rg_xCJCyR_v^dTYX_+v#ZXjgt-oyK0vu+?^asR+=}(cyWN)&PjuPF zSTn?(lG{?6vE{K=AGJq8(8AC1fpxnR$X=DHwl}5>(#pABRA6pf{YVzcf^J`;vAhN8 z(F*A&{nq%-Jd+I{QIP)^0W1v1al$@07*gppY7}02#C1Y^hf37|vw@L!GWxH&`2W!` zl@~wWuq}C(w~p>d)K%RNQa}7?#rdVW8Js_Zm(!cK)X`AL<80J=1%s~;8BVMu;Pwv3 z!DF%esItA9E1#gz#Kq!dNPN+O6@L%bklDL!dzWd4i*y-(5dUX*o0(+!@PeiL5>_AP z`jMoo;hz;^&-K9bbKf9*$&BKH3DLa~bHeo8r#o^{9QQ^n{O2~w16YFOg*y_Yx^$e! z8^#r`18+hjWt(Cy-15L&Z2XyBOn+Rpd6(~Z@loF;taiB{)tIs$ZW~AK#kXU^#OU#{ zv3#W&1MdH_iNC%ucdc5Af~K-LhSiosXVd1Yy9 zx}|^mxwLdap`i0>L3;XU8k+L)=VMUYG?&dO$7HJ()4yi*kHEZx9K-aZoR~W=u^?7M z{YbcO?voyil9-rV)Pg2WX+AIT18n#wpYeP@c$l2QJxi}Xi7FVO|p%Oyp=O4qA@ zi0MT-SL4lh1g2tRkz_ap)4h95h}H{I8U?nW_t-jZvijR)J`-^?%=QS?uQh%7@&X6T zJx;>y6{e%A5-mZutsmP31n>)NKOz{DOBpvyXKX**T4qRFsT@fBnLl>)a(ur>NWp6r zQ=}{>RhH3~+p4T=N%)&C|DDC{oSAP<%@#4QqI`YuaLvOUB*oig1VaSgw$U+vqR*xe zUVP<2FhIb;WE3(T5Y0y{Wxo}7@FMytQ($a9eKQ9Sx3JaA)(G4?3m?f9NN>I0&bvm? zWxFoSC%J$%`?+iCq~3Z2P|{hEx_P3B+I1HOl!TMN5`K0%s4U;saI!%;j$BgoF@m$Z z_n~g4y~7ld9=5H(SkYz72|LCh{`~m*;__v~M-ho4ww%6$587U$#v5B{>OEgh52w8{ zBQ2I{9C9n11GeGd;4Je|*p~HFlm7enbYcci@bU5at`t0~kTGbdb`4?APwIZ{X+9s~lpg)<%BM{r`BGFDdR4zpcMYoB`xRjP zWOW!E8ZAeYF!6HLXcD&Kc7{^riM-1&4u2F$(Ri{^3$z}!{3k2_m{89>Oz+d~KAwWb zN9}bz_ln4=+3j2q-u9YjzQC3CAX@K_*#10*KMGU}XHavt-9doG@YOmxK#zen-)8zYg_qSTFyw&O)**3@e{MS!{FT;sMV_-wBXIU&B| zHm<^xa{~TeAQrC{`L*E{aZjL zG?6;Izb9c^j9W!T5W;(jAeqU9x^V7#@e)#o~`t?lP9ZeauLMzTO7`heJN8cNtQhj82zecNJ?M z8GU==6Cx^HQQ44L<0>CQE1RHuHc4;+L6HP=K2Fa!yyVTMKzBaC!AQJxbu>s$1-U^h zWId_rRA4kFh1ZrqGA~hZFm$lcYR`ZSmU`Ym{lrM)Y3<%HV|PhNh){9ZHyIh@i9B(| z5lvV_!U?DCMzV>TX^X^^?v|31&u;i(qqFWz0y_>;XlG}~=ySu#kPq}XIe*1ettP@} z+2DUd%n#Ih?e1lN4N(|yXe}#|e4JhKrKnf;PVZBGUYFJ3t2VJbgvP`EQlfHaK-S~l zd&p_TJjv9}2U)CF@c<_y!bhx@8C7x$(w?r<0Y0Y>%z8f33p9H3 zX04N~t&DISXpgg<0Dpi2jR6Y%OB@cm>Fm-SxmOTz)y|KkdUomTvJ%vtpK9n1Fw1 z=Fa3oU<0GHhsxkuGGBhn^X3qJS{l4m;gW^chd0q|`)GSvIE`K<;{r{EZCLQC(Y8-y zUYhDiUID#)Yp^FZ%@cq*oZjA0#mC0_>GoNhM4CLWU_be98thAT{p-=2$Eito`JTd$ zE#SiCT9Zxp3`e0k?N6@IggZ8RJ?j!g=eW&G_+D3SRg8NorPC*rKU=>*!&Dr$8f|AM zd4pI_1eI{7%*S5kDHj{@QO_a&79Pk5QwK4L__lVgJ@#*kD27Wo=OxC^ezjAQgfU|1 zoAw)Ry(n@W71b}dK_n61Aor##NW#MV7j~-SC;=x^&6$kr;|$abL_(!cJ6xE-Ko;b8 z`&}8;)}lkja?cT>vzrV)_V7Jl6tR#n+6|pzf0*qmDKWIgi0FrKBXm7~TOP2h-i!6% zz0Izd&U);g&@O3eEHTgNvGVStS99e%ck=cw@|W#P-jvP@W_NoEhLWb%!Uh^hh2?F% z^z^3cKAt$J#z6PVth@ptKr!`0l1HjfbjddP{%=#|ksQ3pBPtO1Je6ZLLO>IJhtZQ;=Uo7lAmlHLa^!K{2kQzb!QaBloIKPm>$h0qs+G z|0aP>jPAa9bd=u){fBtCD8Y`hGM@G!s-EYz{nWeAfkuH5OB$9Qj?mRO4#W>MwM%!1 zM%mPG(=4S=+_QO8+hw| z4D2+At&%5R=Uoau>DTEurF-w}%e;=Nhc|s6h9zlnie~10%Dz*EbP*i5eiWeiv7*n; zoB|*8+i#uf-h8xp(3W2M@|z^pJn4A>VpyHP@ST1aR@8n@w0{VpGXBk*QcN`cn@lha zxq^fJ_Ab8#?Dcth(TSzkV`INvr_ZOpV7R-Cn8oL__<-pJZR_-Obk-bF>%TcP3=70C zp(ieJBKytXV*m>dOq-{a6$UJNzEd$=f;n@8H0PSzzAGy$8kI{(x07|K@i-6~p5lsj znwy`8IK)lj|%D3^3dzGUz^S|@lZp#r-_VHXtj%w6< zIHSB-&JXMRnsn=({iCpc$^Gr^cA9Ye#WYHNVW(GJ)tmD6oh3Gro@a+*R69e@2gc8$ z)}R+~Nkg9wV2;Vx^i3m*&b)Sz+nbBJr20bE7NAz$T9AtqbDSZB?59o}As^^> z@2gq`c25nle+zw1Jl62AXH}aY3_qp7`+2&!9So)kVtNcGLWX`jAtDYjY63 zKgH2tKX<*%tuJ%LaxsOE(V#CAK6_-I7JgS0-FvvlUTa;7z&)>zmwYE~eGR8w>hvv} zG==NVYPWj}71ykUXw>YiOWrQQoMBb(7qHBJG;VxAW&LoL@OOn)>!Ir!GDI2f;LfJK zu4a@>b@TF?|9-EmB|@kzif`&&5KZ#!AdHgC5w$NaGKa%3(Cl-ZPrOb_%6la`KgoxC zx_x`E@l@t1dL(PRU-azm&n!yEyH&O9?6Y`+R+RVe#%3*f`SP^cm-W0HJmO=oPiWS2 zYV*?swQg=vz6D<$mH*u{(1l{WhUU|1>EG0WlX#@X=PJNcbre3P;_Zytx@ssENj z{V^ITY1JbW(cf5g$(NOkl+@eCZ=MCOWHEV&2{E8+kA+xsUMW2lCX(aAjYTFhz3r#lPKPl z&4<7Ju!_)R@wD+R(=)1@x$TZ(eN|=hH*RP-Xd57A*8BhX?|I(0E5H4y8{cGoPmm+W!t4w1(eLV2 znkqJo`*wB6BKCJ}xa4bwkwW+9kqZ`8I&w@?&EpQM-;!sH>4afS=kA@P-)OS6~THkv@uC@cuYwF{vfrulA2@cO$ys zqmZLy|54fYmwtQ2swqaygFE+%pMuP&P@!dtu&Mo?{@w1$$XajLmrw1^K;KN2X0@no zeGbLfYRzQp2H8X-MhkewWUFZ12l-}d+o>CCYO_H9CIGWBlS}@!2|wTLHS@nyU3Pve zqqP+^S*i+pK5(!`jkP$dlPSJ2%RJm;@cPI78H5t z<*v16|04my@u-Heq4YpvITbzk!8~i_2gjH2W!s9Gas9Dcmy^sp_2v@E0*607#!f|H z`$3`~DMwC3pj&TpZYP2IJZ#Z>R(HnlqZ`NE?y^m%vvQz9on93jh z5TF>f;uCev8|9ZY(`X1bzt(PB-2NssRIc85`> z0zlTQdRB^)efJE#Z|u`Y;>J74AD<%8oO!O6phZGg=FsvemG6A4xI~PAL!#!nvbhcu zz>x$=JJ`4b5J`IjUhk#PItj8!c30g=3V>ddH+pfwfW<%aF@BrlC!8K)_C<2fD&yk) z-W7yYXKpre*6{u>_TD=xs&?rYe2u6mU?3<_B}r~_244h3l1R=10+KUGXb=&}w1DI& zAUWsUlDZ`;8JeKv)Z|Qeb2sOl`DPBg&zd#gntRu}Yv%8#d+#Sy)l>DWU)84f+V`E4 zrlXF`Qy+5PYs{4I7(dq6(${>JmjVm5wGb995TQF_V}WJBLgS(t+uPw z&{@P=;;C|v0XAEO(WH=O_(#~A5VfdJ#ba1-Yvn;gS52k*vOU+%>JPzp)F4yge8(5o z4Oyjc9RDyG$Fq?;3SUKZ(QSJHKIY@A_wuyV^I2`j9*oC(j2d<4K95WQA9n z-^-qU^@^G`^+-MG==G}}A-U&u5F0$O7~SgSgusZhA_N&wvD*2^L2A+pnkZIQw_n(t zd&#n;S<_ocG&n)5>5^M!DkSB$8*W5jh0G2~6hKAp=gFjeH@nUmm9vD+zrPig|4F(z z5r%M&ok(e@&h(jZ(%J5hWYg6EzK1d@+{L0wbk1H#ra`Ybiqoz6wD`1jT&fDnGfORF z51nbb0$C|wy?fMqmxvJ_NU_y%%kEQIs|=!~A>LugKRe4Uyzyjp`90Sj!^V$N2cs=N zhhIW`C+S|!6FXgmCibvfsE#>y80P5fbL_X6m0gJrxZJg*Py=i~{8W5zRRgS&Y@c^7 z{8<|44f9Ox@o_brZye51)mJlpx*Veu~O|@15BNcEE5x9>V5_i?r8vVObu_9V7QG74g z=7CG~DwFtat0<41dN-I&B>68b(3&nkAUu1xM_Y|nlb4=JSXR?~Z2MsFQ3vcWy5inr zeiyUFv8pVVyhvH=X=|L&O7DQC7+8`=(=Q59lGp}28o?qJg&KCK6Ad4j>p^YqQ4e>P z4<;8cdVtV%x{`Rnc}=`uqsp6Vc+U?;`|C+v`d#pKmMotpzqq1wvd4(sAK$l9k_Z3f za@i|7t4l2fRP56DoJ@1TxfAgN_}u5E>b)c*;7RgWRP5q$9wbEoR}yt!?TiO%@MP409@FidBHMQ`Cj$cmrsZf`&@-+%^8@oTr;LD&rK)iW?o2Ij zwVh%ZV%T-b#60&yFToGn1&v1|9x`L%YLq~J^_#C}F8tNK#)GMl>$Avq0@{M`hXK?y zBIp`bHg6M^?z&UlyWI#`;}#zSs!55hAhtZMC*axAYJRsP@z!fra>l7^>d`cM>;+pD z!y)mI!@W_rQ|tf_L2ykdT0*0?8%}IXLy|+)ao$N0P$(w==7H`gX z8n%a!LQXoEW_D?l#^#`W#{?!b9ZV^Kuq4xoARg)k`eT&zu<{aY7TM0xO85W zK)=)8%BW?2jCsemeRy>pOALcgZCU2UnfwD0uB%K3{-A7_W#m4Bn?asbL#m z_QMxhG-Xx_n`%qctbq?DxbLa6#~fQqODjAO;qSaUhq&1?sGBIESz$9M<~sE#JQ*}O zD$*aF@45J5a;K9{{_Zmn;wdmxn9{*4=BmyLR4a$r`M9-Rbva$wH*DV*^K3h4;&=9g z@`FWeuIS7;t`*E&)aT;p#WXLM8nGCrAjhcty`w@ub#;W(7CVG?*!hw;Q$QOUo|mVtQnNSg@I$jH!TQw2%Y&SAen7fqzFF29w?cbTC1v6_G>}AKZV7Jw;_^hSy`6pid z`v5%K|2>y-G^X$}xu-qXCgbup{|Yk!$XGjS(y?A@QR8}dlF!*bz&aJ|@~S1NvA&*u z`S*8p6>MX@O7_|fr+xmHg69tRXRxHk)sM2L^L-8*R>f7X>LzRH>`h+H?Mf5Q^m2ML zkawy-KKB>N*HKr>IOrOH&knD)HruUNSj{cQi&S;ENyj9WWYr0;8#HibF&S+Q&NT@d z9f*}@a+{t%n#<$LXP{el3_N;R$aS&5X5Z-M21;Mw9@cFNC+r_gY{qys< z&k5iVhY!{8$w}4OE%yJ}zgc@;7#bRi!1RGZ&d;qtaGgYjQQuk`lyjJoV?qSY7Qxtav?U+(1mz{|zT`bGG<0rPwwYN&cU+k2T6vg$;R;2{nVo2=vWd26 zIdpVHo(+{w<1Sf^K+g-=Wk+2)^GhwqMjJYxF+_%h5^W2c!@t1B)pXTuI_*E%CpTE^oHp9HCe@}j~CpFGna8$^$Vl6!Y1BEQ!L<_4&l-Zu@-qHi4B(oeyKh@3@7s zC>vUKtQoc$NcG8w=iZu%d|5O-R*l%*GK8sp(o%;!CZZB$gsvSU)o6Y6C!Buv3$6@? zSS|cySX5^!zmlpK*G;C!%f2tT**#7krFYM8^dx=vNW%S%%1w9vcop~I{&#P-9;>8e zek2{}3%S&nK>CX_KIA}8krqfli+1kBwiPRlvGz6yEc+a`iNR}qfGNcG6p4m@}I<%Q}Bt^$2{vV?qumVx`T-UMT^-IGPVqP!rv87UK(s)@b z$bV>PX&FEA?4k`Z0e-O^9^#pTle@X5LJDKxBo#7i34&y;b;NlnXg~8tm&)l%)MEco zh^KLxVXeJFYmF4B_VP2a@*6>fa1}BqI|%`yjn2cN*2l&(KmR~Zm$z$HF@7c(sca-v z85TOj=U-~I(V`_NF=SxTdb8z2B=3tUC+zGviZkTtJT#q6=*|8-5)nVJGqV~yd3S_H zfGf`+i8P8x{Gkkkk?GM)?y`x_h%=syxA|F?-F{-%+<5o>j8?L!H){LU=Y%S9&0R4; z#*t4S`^35UUsyTS#q<@9>8e9my?Hr}NBM}6mB^9qd!fmn+FS@}!@t#2=}kXt_j5x` z%%Q%>a)$Z2D(k;a6x=0{2uf9mBa^7}bXEIyv1QzJ4ZUNs`!j*du1!vs>B64^3fB&( z1Nw#RG1iY8Mmj7_%9HHTPuuyCcCsbHT-$!@F zVK%^w5l$fZXhml!3M2D+@|8NJBauiAzgGe3*HZaD%LW7RDcHvOI{7GMK4r4rj_GmE zp>v;%n7qUdv7Ir0NV=hZUxHvCBj_sgRbo1eu#?=C+j05=W><~4UGvG?+H>u>_EtS* zC+|HzuA(Zo;To^JV4(lG8i(86xG`+^yk{ze!gEg%^0xki^JmR+*7z%0dMUWD?{!?I zxm5|{8cyDnIK{o%bq=}V0WlG0>j~#q+wXQ0>I~?4=D%AHh7bO$mQsL$?5ge+f2lxjCl_jTcMY$xPl4E+j7c_ z6soGls1yWrxCLpN-e^%dHn*2<^zs=0_3xwD4K+5c*y0aX-SzFs)VHy0Y`J^pz&cCfW4SAaG4o`C3r9*-2{I)E$=4Hf{O zn;MC9D;Q*79#S5L<{z>BP^NKQk0keZStHIo^7Rx_YrA(X)@z!Qohd0JW{PbrsD(+4(6vR5uEKY&xXs0NwufrqPfxG`)<% zeb3HhjzL|el7DQB&po2!c#@5hrYn}X*zQqdWcN$GCNK9{n~nl_P*@cyqC{7tEf^sy zy(~~1LON|ds*F0d4tb3S{*kM+4gMnmKC5vunwV99 zD4`1wB}CSLF*ONnhJ@`OfxHg7pBBc+>=O6B$%e|eR5%nG3dZ*cR2q9fQ<0O07_XuS zX;dIP4;G}knIP_4ay^O4uV6P8lkHWLM7j1j zOu#tpU%u>2baWGr!yVB#Ox|t3+xQ(^3pp7ZE4BY4(jnD;MaARyXA19^tP&qDFE0_*i2u81@XuS68hH7dpr__}Cm- zGd_Llm!6hZGFhDQ6l_tt$$`u+j)Fh$^)anCExh4qVbnBM8M)v1Vx~tR7NN{p&)X#6 z_=XBds63!v#d82>>C?$eJ^<@zD-mS}+q%oxhPy;Cq`AMlmOYalYd|%$nm3zc=T+`q zPYQZHK-N5<{ODe3QddOph zU^vdstIlm>)D4bJY^Xgz`Mh3hI9Ye--Pj03?@t$Zn3UO=uuwI4{%Ud7KCwgbpgL7S ze62M7%Rm50RV$l%*t$w+JWN@Pv>`OKCC^lNo4Lr!+5Ssp{im^}yz3}r-D_`Ns|o55 zf;2_-7NZZB1>Ip~)~xdX0hQwVwtd=!sXRQAIK5pS3nyK*q=nd!7b;CWpHH+y>Xx65 z8xv1^to8`L{)tnmK$+`^a_G9c%9+84R!X5>00z|)6FCTSV*#NkxOq+WMea-H*biT$ zQ_()hybZ_qbehHvyC zuuR??bGufFeL_0~rG4+A8Jco(Z2D#N3mEhmJr&hmCa;Z5Yc^d)u+Gv-NlG3*@?fjpB^fDVjA$l$U-mmB8s_&C@Gb96$ak{q*UGQRQ{#IhK=_EWd7MXsZ#w}% zZQ?Rp0KV-!gUYMIay;;DCybY!$WifokTKES-W zW1+_QaO;V(*n`x`EN1a(lap?CnLdz8CCZ&aQPc1$Iz^Y4Faw7JoZ*CmbwbZQUpvem z=Td4hZq zbAr9#fByq;u{EF3xLixJyFkb+z%FD4j!WiNY%iXpd}|1dop@N{BN54*Wn(OBoMXK##x((&L{o|m9)i?o6+i+)A8;fCU*;yx+Bo&tK$;*ryT5h$$gis}f$&-V5s^~unKfc76>{T-%0+aW_K$oe=M`CgPe&y5u7 zj=UY7tE*gn#2GJLYl|M&O2iDYy9X)8a%^u26Q`crV#)OzZ!8oBkKb!dIG9n{k5|NP zAI?xTX&UV?732o0!gr(N_G$@d;|Y)m+sOopih(t4wTR2Uw==TE@7{$m7j6vyt75>a zwOQ>e9KPBcx4lF8i1e>vc5GBMoWX}+*!H=YD|A@slxA9N{jg5T3nWvH8vnqhZg1%P ze2dTq6D9b$=?lWuyU3okcM)cA2d5Vlh`y-Pl#y;`a!~kq8FjA$nH;==a%rqkvf`au~Vo z*_OLwX`ry3@y9SQG@7F|> zI_`5C7k^#k+m*0@{|h@)p6S(yaWf2LjdbPo=E}|Ic&X4UG1GryvXb-kHtS;B;bY<; z%E(o|wW8&X&+@cEA~N6du!r&vTUE61+w5ReQ}T@95-0GOk?G->4Cg;;9Kvk2RVF*L znX+4(e^B187Jnymb3B)BK?%+sF65)*7}PQcPcYpdIs=>@f716*)^o#r&+%~3P&nSc z4zb*fV>T4!>x{faSU*A~a_}=~>jz(J#^$^>WM$Q4rh9`X5%X>)Fb+3b!>lVJ(2L!M zK->q5jprin&IT^;%>H4@YHyy7zxUX-h7)m%Ej(|%KC4)FRK#MVv5tlwP5iuxsj@Gu z)B%ZYjnw{Ns#1d~739B8po*T}*=?g3&0wKP6n+vOZ*Ls>#FIOVMpa`Vm+`bPH1U-0 zIzbeFfWEzI=*hxw<{TXo*rb?{**BQ-es)Xqo6{wEA4(*3#7Ex{nh?2wuon_{^tDER zRx>76gGp;?lV=bTmD@)7KZr2~0|_=yxpRvj6)kz%-(gk?zF-*kZr_)l-ujCLPz^$f zV7hfHM3&5ee7^F+^kOeVQw|XH zYLxMQh`LHl_li8H`|Qk-AuK#{@Hv|IQLmt*LTG|G+j?;g$JM>()DU{aq#&DFQjBPC z(%?%SwaClRZ_BE1UOM-RS~q=yC?r&(PK}ZBm;udXWL}4zvudYyWArtm=ef@bYhHE= zG5!%31aWAopzt|Z%Xx9JrG-zuH0_Z)MsV5v&-kE88$*Z5Aj9>(0zrZ6r=Rq=#IkVq z_UNG(>CVMZA&-tU)EzW?aMurzZG+Y=gJlDoamSrS4&CcgR!t|d=Wi9s*CA&NCav*& zUNO~T4jC&Ic#ddqjmasu;b(nEpFo=1Qa@-yy}UsRCR9FoKkY6l_P=g=4&6`I;msid?Z&jviHt3?=UN7{Cin0mJePxIw)5K z${${{Ryu>~nNqoV8SV1y?+`UPc5N~mj7D5G?MMuqZFZVnI0_MS%vLUrG#=gNBD4 zbC9(+LT)n^6#J_YdoXs{JMT5V(a3TXxwm)JYEF{MPIIT@FrABw2oGUOgKj+4Lp_WD z%4u}8HETTAB(0(@fVH`_(!$K4N0QN7S7xSM{^xbidh?$+DZd39Bv80TFG;d z(yriW*!sF6^+b17|5v1Re|el&=Y_4&?ox>3+teH#L8hagwhqX_VQ%S60`PIq+#R}Faq<4#jgo8DjNCcE?xEE-I8OTm;-zi9ljQQ-vjbgjXXSWC7_wrfI z+79#0d56Z4c$8ua^Q?9kTJjqgMo2I~z{InW)wKO) z0y7}zuzriLc_i?<>WqB;MyN_G?}WxTS%pw0AN>azO-{CY?%u5%M`2CQ9yhfmsMuI_ zHdN-{d@^2H#HQH3WvbNRS+z5|HypkoD`6GR5&9wFx>uO8?VxuVE1Zpy5zE>5)+@;q z6%8@-K>rB{4`0q^@-=7e`b{f-2ezx!D`NU8R3e|B0xj?;E1Wj6$Yk^I#KfZ`Q*ay8 z;jnIz>+UxXS?_m%EMw#fD;l=yQxgRQUiswCH}Y8-?*Y{+qm@?9eRegICkNB!vy{&C z|K?%?_YOeT-v&^bJOMXo>TxT2tGSfPX1yyDC9$^*Z)4|dBzf#QCRQ|&e?;=OxqD8r z4cQl*>(eOlX$Zbt9mK(CM92Vl_O-k15k&!9liX>Vn^2$16D7X!w5#+SIP$DL5i`~+(1H~0#YEkAQ8iSc(PU@QwqrCT%vRTEn_D%L z9=k2ume!Oja9LBjJ!&A*o-1B)WMiAz=FwZ$wW&4)8AoZmD?{$N;cO4^9ylONpkh)?8B zUT-vQeH7ts^hdRb1)po&)lfB1CB|szS-5~ei-~G9@Cz=8i;0*4b+XYNCRP3n-ym~_ z0kYb#{U)uL3QaAtS#L207Pms^s#DCDZ#O}X8sk~Gj%0S>4BGY!VDL%I*s``R=jsd~ z>O-^)f|5B)yBGC^p~Nnq&nw#*>AVN1T$r$~cz_R=JOc2KWS`JoJb(Od2A~PH{5rSr zM0QIUV4=MdG9J%CA(Q0mav*#Ype+0ZI`hldoV|glZ;>{G|G*w7?6MIb2?C!*?ZeNh zl%@+x(RRgJx2u)w*>T&WCP0y1+0w5Jb1#R@--qiCNMsetHdcg$1st=DGG72d}|ev9qBA%3450JT-OSH8!PBgYdw>6k8^l9-%DNKzQTt*|S~(@79VMX90#P`+{0gpf5~((*er8fT8h$@`taSjFFwx zpO~K@a*4Y`NxKZ}wrZ>=+^sD(tl8v25SlNH{j&@FX^p0eL$}~z3G;Ln5{c-@yqZ_< z9K_cVS{oBnnTvIIXQz&IIXPxJ0Bn-?QoW+X@K6>VNNPQ=y_vk(a<9`!WGxA&d(=#z zl8lKZ?2)Kvzb&sq(FcD55c2 z{0ivr*DByZNeNa_q@n$;varxAAFx+&R@U@pQa4nWbrfH%(dB>603Wh2mjrM@7eDDW zgLUfv|JT16#{V7maGO%2+}!4fAb&P^ak2fBP4~fSUU@c0v~_}HY(pUDE?W@oKAIe5 zqh4acB$DuN%LBCM^W!sIu1Kez@e}5#>7DI-FxCCPO{?fP+jQk;eHlV#I0I;I12$>A z|LZ=;eRh0xh9N%TZ2U|_;7QMeXo90sezEg~bw@^Bq-7kCwe#9*f47dF-wK&)qEM~U zR1#(eP2gwb8I}p4rdg|E4R5k3%1=_*hinart~DIv>K#s2ixHU4YNs?E1`v+Jum4^C z1^;CC{rmKvW6iHxT)h=rbpA)w07ks_mvbz>qAhJeMUzeGcm2-q34k6F0Jo~hUy}@A z#lGfD23$?%_pf8mt30rqK>iI#-$}a3oi}*EE0U!FWKmn@ZwZji0> zV84u*rLAX%U)fxjKD_?1fv1fTluurxC~$JhN5J4@(9onGTE0@fQRTUDcE6AOhn6JC zPqiG7aic{et_~v@jfMHb+&~oqYAPskJvUkA#rANW$j@BS${dOP1shn<_fc zA+fMf|AD@+OTCtHDw@-l@Y1axjkD!hNEajTV>hw4qSq%)}8m^AT4OFUB%lpjte|)inQ$BsTF0?otn)yM zDKsdawAJL@WV@v+9&Ck<@ZT^g+r5J;gpcxAW`dgtn0$@V3M~YY$S_^^ziTJgY^tthDoRBGAY zr*SDAXH2R+B2qNNeOtiw)SdL!3L&JR#DT-tp5Zy7OpPk*q0RK z{L=L&+_B2KK{g!r+GzW5=c5tCswEn-(wv#^K5IPc7Wuv;9_`|`GkV=5$_atY8NZcL z98WVF`5F=xJ7TCykpcI4QTK5OC^`=4Fs$a#PcN|=IW9Xsn9lYFH&>#Iy|Oa%Es0NX zcDJ+x<)O>r(~PCQPeg{;1ei0MFxS$960K5W>5M`@q(T^JHWSbFDDvogu6FO9)#Re1 zm#Zm=Lo$?U$!G8Q?aC|MxRD`lZ$0R^;5ByEZQ$^(a^A*f520Z=GL}887+vC&q*0}b zbp>^zxNwp0EY2izRu+@er2#lWxqi2d#;*z>fFiB~k*G()mJ7eHQd^oz0Yw;$QcVk0 z*;5*NquoMJ|}qwn9Kq}>V1iiH}Kue|BL_Ti>XRo>F#BDxz!>ulgpGEI^Pv5 z4bTf_cL=B`Orgil!|N;LVBI6Q5%+Y|_b_p`UqH`CKgk`jTTUQuqNSUXBJqaHwNYIee>+k_-Ui&X^U{vI_#Qk$$1_k~Sk_XV~V66Kvb z=NrdQ($<@PH+9Efs29 zJ?Uy!7B}g-L7j@8mXN{W!bdGnu?eD#DE^|tqVQAgEseT@!T;1`;9^UL+Za2|WVzkM zmyaJ$%NrP}#!J@LQ2i!jiIB8+C^ACUDOc3tVp(-$Y;42WjKf&f&fuIkMal#@IGXak zbynP=5PevVB?`4$FY^>V*)P-5Y&7~cRx`gxyggItXczLAyveU$} zi`37}x4*aXY-?_G{qcWKqH!_xZ2zO0jqs7!w)Z;vEyZ7>f;;&mfvg8e1L}{JLL2A> z%fYcA$#WpklYimpqE%1NX)a{721jP5Dg;VQ`WQa`M6iBpa?Fk}Pu zztQMsFJrD6A#TMJ;nDK95@$(&ZA&l_=e;E2Ea`9i!#NI*PkI83q559oEBWMB0+Rj? zQdzD4K8=6CQsc_N0=;8&9)Tyl=tOdW8csacZ}L zn{CKj!T7=h7|n0mkc4i@3dyaK*oLOdX&Ki9^oHp*0jbuttf{yij??q{H5}ZAH7S+<+9MB|s{47Dnj8)E;T(y`MBk!bl zP_GX0`p!B-3-dCS6J7#U3Z*gmrW0O^mDqb$1-Hu=7sk!D{Sn)nEWJZgvsukLE0LHI zNGoyl@qNiHkk#+P0OZ zJTII6om*DA9<~}zQr&g-9us4OIt9xq{*d``hSHF7kD>t;(3E`B$(hmb?Yq{)>~^rX zemSQ_R>{U7a&|ZaRrb0(t*yK6-h!BHO=y)jRetRuW`p^s8d8K2cYIgjUPiC2hgVBc5{uGy77H8E+gCYK%zTWbo7e>^X;`}I+IIX9NI5M2$x#P}BMf~ZfL@I{zPQ2oquX$~PbHs}{!k_dpen{3e)QHAT4vvz9 zDGSJ|pPHoaA0}`}wJOB(DQ7Q#B8^rN%i*`Yx@O#&2m{ zHa+=vAzOAS_ihyyuI!%fYjOJf>5?M?Gss+pX{53d!L)<2`c|$KrMZyCdi!VHH5pE& z4gzc;SE4?-O)cYb^nP9c0<o$bRkuZOwR#6Zn0v8eR@Sgoc^X>_l?)Z7+A_FbS@ab!H1)5<_{td_G$lYsp2|Wj6 z4>Mk+jq*or?(ZtK?Efx`4X716w9?~erJMrzIx{tgUxqE-4=pN$$r7lym)gY-en<-RU@a+jgkB1?KUn#IOH_PG)6%}-7Mr(6x-;GK`wr8u=#5f?q z3!Ic;Ht9Vs8>3#LQX7}s;_-wIRC?N5UoV^c7`j$Y)}Vh4~2(A>bLfvJa-*C$@85M2L63#eKB4m3rM#QIL)A1X$Vnib z*Kdss^oOi2e5we1K3VmEa=q3Lbui3XIRAj=ZTR?CG`mf>|1uD%*R8R%M{`yvaVEK< zTPP0DAsKa8+vg9BX>Nn9ZJPa+@yB0V(9Pmi4eOZWn#0Vzw`1nMkJl#|P1kI;mX z&q6VW!CH{F8VYjxbjt8_8}!WAyC%)MzphXciC0^wVz$ZMOg%B1PJJ?}FMMF4hre^g zDxi#}l%K%hsxS5QOHJWNq);B!rIqw_Q686)0JrP57NHg!$+siO|GY*Wstvcb^|1v9 zX=cm%8a^-FK#k)@4n% z8HQX1Vk#TVW^qp# z1SX!L<-S;IPnVjCVzC=vG?ChdDfh87C@MZFS;WVI28m)>P6E(Xba@{j;nrwcpUh_F zQMj+SmqLXius|ndaOlp=cL7EbJ07^o3G%uA@+AUX2O^55^RPeQKmvceV3ZqHgTphn zbe0u(|A!UN1788YdCY&~Wxm_5R_$|l-CB?LO8+QRru&@YmhB{SoptfJC;Kmfr3bt| zGVpR~g*xmgP6wWN*Rv3b6!>7C_|D8^uqZzx=Ga`OoYyR@Zvi-h2i@iCO z7^~}kP;9(HsyZ__l6q%acRRIoseZc4JH>hXiN$Gv$-K|>WMZtQ0BD_(7XX|=>%HHw ze$-+Q*4S&#M0M82WV)&F`E(O>R%}CzlSpXy=izp26GiJZmoW-r2)1(9?&(VkE`63N z&p0mMQ%2e-i_;M7JqeSG^uYj(RB_Jbdql1cjmU6M&j}9{JH&jf|DB7+T+O{Ic;lgQ zf!2X@RlXmQyZaMoZCa3Yc(T28zVOH2&(dT{inwjI&nCFz*1wZ`F zMlmMg)b|W)58x)yu^q7()+#^Q#sWJ%!KE7G)fgP;!gqXh_Q>zSoi($e)d-h^X>tjl z+`|Mg^MDDz*fX9&o}^Hf78~d2$6%TzyplK(vz(sw{Vzwinp)<#QwLE81#5K>kwP) zL)}$mK*d)q?wUOdZXSN^OO~WXLt61=1V9+2q1<@4Cm7`h0@H829ehjF`)vT9phHkU)_CBAgM<;Fv#oqTX4a_1mhYhK-;qGc*UFGUQ z$9CC61qh@=Y6$XH6eyTUL|+~kfv_QFwhJ3{Yz15WIv~LYTH^zB_=PX3rrUcp_Y2mKThS!eWQBb9`}9d3b6qa{Fy?$2kS1KKShw9f_}ndF!k zdOm;y?5+_2cMw`NRN$+BP&(^FGp}|Zr2BvQwg3eQWW(<)*zt@d0c8_Tow?k24#yv8 z5B>l8!M#iw7~jq;^Asou@xe~!9cm9mZ5dnlL}^$caAZq&O}7?S9?uRGQ<5%mz4#jas-8u+_~T&=xfHw1)p6;)5JDsq0w zX@6Y_=AgqY(9-sP@~aGJ5H-7*8xky@lFsq{gqulm3eys@)gi&#Ce?=%YC2kKRXIIi zn#(kZ2HBTjxwNH=Eyz^V7wXhM0k;ANPT=Wrh!=+YfB(LL$$mjFoF$od2n@AL zAn*~g(sTg{t>y&>OTcY<#>d)%mD1qRhb0X_>Dj~Z^(hKA1eErF>C&$7A=rPFILq-C z*gVP6umacINa6qq-*K~cwH&I!Or8B6IM=LTkzdy}w%-hwQs$ekYtm6-A_!9W-!tbV@>WX^2lx{fv zU5k1kep~=?m^$g5-bejkKHNY-m*w);Ur!R{o;_9j=g~{%-dK|n)kxwE3(0B=>>@*8 z>W2{@XFZ?es(2BZ12XN~U-wE^m{cfjI-E2|94fdsAE? zlyyO^p)VL$OH+Z|urHzCFND=^|6S`v{#DD}rW+1)SM}TnD9tf~B@d0{Z?GB)JW8;w z5z$b1@zh9ON}=OptjOOnis91JVh@}4d*zbDd*CAeUn_Iri4RPU^JUuhkDLohyXB0Q z+frKksf(kK@M&kAgL1YjAKgXm6VA6|UUTz}1bEu|j!!29%2*Oo(Y;M9Jq1?QVl^HJ z-&@xQ-kQ#IC+sWm_$Ln8^w2}>!2F?;(JIA=(Ra=zT%TZ!oodkHyX8VE}k}ouIV51Jk5iYH&W8SR}KY&6YS3VNQ)n63kK`dy%5O`f{%L=TBK0{dm%mXSL8h=SYC0DP^40G zvs?+b;kj<7yg_fB+A}g++vr)6RRyInT6N+6`lrT8$?g^bigQu`D!1{d+Zvg~55dCe zvl^gU3UbpjsSmrB_Ae9{O28F$X&)~ie|c$Gzh>F6pV zv!GBDQ+4kS2Q+6^uW5LaVCFQY>b@^^@#Ij`{%o|L4Du6_Hn9CvoQDxs95OG^7c6H^ z9J1V%FdlLU#`TzQ`$ncdeK)-l?eIdU-ED;D+5mN_yJEMXkI`x&#M@heDiYv%AMDE% z=7dKq>Lp?8U9p{l2Q`piht6i}MvG&Cp1O@Y;Pbg5b#^|rv7uuYeAD_w`Zow@v51eo zu+8=DOsrZOT4gyUy$g}p7j|2d4c4LA6MFaRUI?GtRDwSGot{VV_<6A-p?j(G50E6; zkd{1Ejg);-oL%oemSvb^S#(J)arhjjmVQ)k`}Hi5D-)ltp+q}0JwJTu$7 zZyi*-8@Y=-`i^y&#%W5pg9H)fg*1!*pX;oo7yihlzpn$Ej%v0x7uBA9JZ zU&)tsXYV(_ea(d!k=KqUn7Th8iWxzCxJBt&HkE@j;kMm zuyyjVq?|mc*gcs(!6N<+&pM*u)(3)m=#TU=-z5d(1if_BPHl;qVcY_`J$0LA2_}C zTN0QI@$R*`&12mZA8~PPZvJe1HjtGmpMD@q7>uNJ`oP0_takA{w&NtEDN~Pteh~%n0&Pse^oMNy+Cjhoj?{wePXx5to<)7)Frf9^jKBUN&0y zP2&6^`X-&l*KsOGqrXSmJ*^Dx<_p*ck~_70IgJ)|2Dr%9Qw=nf$D^&p?L)DKG(NFr z4`Nzk+`YZu!f_6593KW=mHdtkAE|d+nYO8B3zi}lqGvpvtw|0C_cx;hjFL1ZNzBY=rTXottv|$2E`D2#YJ<%L zN>$S1jp*K76u?>_Hr_gDqBKl8h<^3vm-+d*{N+mn#5`iZ?~Q+rQu2mQ?Dp6pF~!{> zJJTmA%*w37c4K7>y@vtSZ30b4g@WrfG(O#9F9v@5MSxXF_CpeF!Nc?QcZ94C@V&LkFQA^CUlJtEzG{L` z8!!Y6K+MVZ%Xh>E^lTuldf~#?6L7)9d&%p7cFDinbit$Q|Dm5~+DE`&XAnKC!}DQ2 zNy#M|kfR1%SuH@sc!$PIAGDnR*n*V#tOeY=*-6%lF>33D@=}s4Q5(G zoXVWq-8o5fCt+qO&H!Zm9GTBzTFwzZQ}-#Tv!d6Q3)B4P7wZ1Z_D3s*$U-aH5JT|+ zdOEhY3xntT*`|$L3AT-hB=0XM?RI^cn!c)2JbknMoo{e#13jv6AL#CXlA{coGxYZ7 zbaY6H6Q0AoR|6dMcY>EYc*fR3fLBosqvXKl+q5JEuCIMB>3eqh zdi}+R=i4yfn}BrofplN(`P~8p^@biG%D*q=9N`(;2Z-J^oF4kgs0k7tjwBj4eis+6 zgOdc!X)@I!0}4f5N5kp|;LQv+Olvr-AC)5J`8sZUjdyyQgxzl?y{;^vZk(u6^cP7v zSzlNJYy|mZQpjjTeP1ixVyLjx-k_~rQ#o{Ha!DQ*P1@W{JKa>E%E>RfrKM)`j&YdJ zCh(hb(W`U%^s2ZPrYrdwsivj2tG_`QllfUhG{_d@Y))X=TwVu1+l;rxfduOZKs~4L6+j?5nCH^4w|{6u~y`=I(8^PM;c~ za04VsFF0-9=V5DPN1p7-IT-ccj*0z?^QfiB8f}*3u zE)s;q`^`M>`#kU4`0M@q=ilqz@6EmUoO{pbe9k#F7_y6t-RXaQ%YQ9+IFpxDxs_vq z+>P}EQ!gMY(L1L0CbXJyevF;1;Jts1RhP&=_+tx+#XYk@EpO9CJ4-X<%`D{j$%ChA zjtV>z&w{kiy%Zrn!Qm((shVLZ)3}B^B!Pm#{_1DCD+_K`_@xgilF~{fm6!$s;X>1$ zYv#8oubwn$4Eg(|d!`-x3F_7rdETv?8tvy{df^QM{bpeFLad3+QzZG7Kl`~@z(4Q3 zTh-x(?45CItfhAld}i8HbvouBA>*NbTlih*t03bCx=vUow>0G9kNgghv_~LrK2V)H zC!W0d_0f`&LbXk&2Cx+d)<3PMuFdidB1krQK1)xEEsiMh z6jXP4by>-EKFN8}P^#5Asv;#^Qz0(gBkvVGU{-J`9`*4)KM%1#&aOt@wACX1RaLmH zdF!34Cu9a0jwlmyS;t7A>UXj_z#ISS#cI?PIL`I7<^6V*V`egC%VN6Pm>sjQii6IH za{Zc}9#L_>KXxOVzb6mr9wR5!sYK=fn$q8+M+JjLCJp74o&Hj=l@=}pMaR(1I*w?A z;yT4=@>KNY^nAL9NfOn3MZ@hpaxkeOWcJUfickOwA-1ny8gg3L#*TJ=I8bgPAEtLC z$nJY*u@V&P!A5%CkLxTNI^PP|dMToVBS%LHiP2=Ts*1gymOQMoZg=i_fSZYix1nJ( z(r=2+FEsO==pbL$=UgTMR;gfJ##{*7iF4e(5qj#9IvG@xY!Tm>Q#>g$XTe&}OijMh zUKp<|q;STWP1lfBi_Ak|x2Ns%OB+)4(0-JL;4n%k5|JM7h*#`7oB^ccczoJhD=o(R zM~MdvCL7LLrEeI#?LL)CPo>r2uE~9Kx~Mwq@~2D&3x#w?gS+f)LCTqJw`e0SJ z7(0O(o#An{Ej^_e68l1LYY5pHI2!g#3cI3ghk8@Ls5UZUDN<3lMe5>`GjmGFZ{7+# z?Dx?M!HR;)&d2|KKA)g0wYa>y$nHp*o;!dih<1giBqw(ap0c+zcXba!_k7hUM2t3u z;%7*ae$;_Us;$+FPzm<=^5d9rxih_9n)5=-BqW>r_4IjjG4|A5@ z(TinW*$@1mbAiXXsKbCPXQI2H2$%E`5{;lq@bLx>NC+4(WrYX9ZyUcT=2Pcv?@m15 zn(cn&x2C{S6P|Nhpkd>nh8ZHt3XqkbrEJA5Vn^>NHOw=uI$xV-<5d`=JF<&6LZU*$ zlc<*zMv@d5yPb|99&%Mu_03+P&Tqht)oTn`+O;Zh`Bf>Dd2A(Xu6OHmYC0)G`N1?1 zqMHfNwwLIW+P)4s0rS0k!aye=**w5Ww-r+8HQ$R(P82b;B(Kk*C>E*&##gUabyhd2 zHa3P}(5Twj?cZwbRGCwvP_c%o)g&If8m7Ve}g+}FL{dIDt?rrH2YT7r3}crNV&tq&BEMzb6+py?@4$F zP^2K0=|Vj=*BFd`?3w#Rycz|>aCPg?WlA0n)1H(~veXBsgl%++p`G3J7>&Aa zolOO6Eg4v0xENXFW??tDPQRIFjYW)${#9Y4X=i>Tp@X1X>o>52Xm|HSIvokQOji7m z*d6YBLlJ5(E2v=+PZdDXD4_7OW_xb2eWo_ zI)?+CCfgkJXLDu>aR#SWaxk#4Ri3mOQ=;fB_H2v6{CVpkL*<0O#=xY2w&cW+8u+c_ z+Q`LLwZf0fzRg}!D(nTQD4)!>UD#61Xovi)a+gT(q$WH*F#~C#bQTGMt24fAjnvCp(zH)^FX^()kiP(NJHi1>HM#2;5KBlS^X8S57Qv{qEpU zU!IWJvUg{E=oPbHa;CkFNlZNtPb*)jY7^)QXX3bI@r=8kM8K;?aIxlp>@(PRkd=%g~mBAT`5%Y2*lQ(=^76zf0bBq5%bvXS+8Y& z=q;XqI7L!NHCPrMN9~zaP{&wGirldyRgDK5g_W0lU?$KC|F;Y?dp<(ag5>njywLX# zyMc}ueo?0_y`;%4cRo=%LJr{Pz8mH^9Qi|**3uFhXGw-yY7)!0#FZpvVrMmet*d6H zim?dCtaWpXLrc}UuShf}k>R1TC!jC&V5(_61bbvsc%KBY9}<{>Ddy`-6mkaS!E@0dJ#AA`fZI1AM<7CNGx=!aZP62NqryB49fpocj zjI9sJMj;i7H?7#bUO;t$aM}VI0dQglux}sf%zqm-yLIapTjK_V8&Fs`1wN;3oS5-+ zcg_$irj21O_|1wi6Bg+?zbV&67ieMzaiY*v7S|pV!~>sRk{+_TJ&H)eImf4}qwIh+0q~(W}02 z&3g~FXgppW5}+m3M5WHJJrybnqAq(XT(|%N;Up_}%;RJ*_JCdS5bRQBs5Y~Ar9n_F z!>p|41e=Q)u=oqdo_`j_{~>67$BK=#ZQdxbcCnXOsL~5qsmy04S5g$Dykyseids}% z{Ducqm(ca?N|pw1Feq!R&luC~g5~DrySlI7dwI(*`?wyY41136S&%*cU?znq^QSiy7%*usC=fU9RPO`JyjZ5O{Dk#|g zbyQ%iq(o3})ktrnapaX3BU9{RE?spo>-c_1r2oN!wI?ky{4T0hatJPbJy^_;Y zQ4)v;NnrI#!-ms;xUcx&~M6F^VDy-YC53ee5%M2p}fJ0iXS916;tHyZZ z=Xx9tP6_lVL(isdHGY|K`(j65>#lwOire${=xqW3+DV(leBD%nZaQq2$)4k` zNo0iN3+8b}^1b9X(Ha{{ zj>l|>TX*no5CA<^A33rQ)^r93;7}oYI$SPgK(FQ218vR9W&7pN2;tP~oq0E~Up?Vw zWq=^%?MmNI{UHF=C?l9q$SqSR=e&Wo|JT+%-((ySuw_AqB4tAupv3Lkhl*El<+dU)|lO#Hspkq+?z##+K+>>1}#3!h=7KfpAFzk~f^Chb4c!jf?~i z1B9BUr8UF5wTr$cW}J+BY;EGk9X~%Z9-FUV>`?q($3dhwCKpT;(XjLwR#~ zKmIZfW(Ux{9CHs9jqTIs4+M<#M&^OJMm)@Wsu(z1Mm&}^Kg^N?SAV+#NDiM#;C^@H z4GthFka>5%Ljpv#TojF=?g!rI0)lf;TIVBo7~Yvb`G6r+PK|Jr{)}>sIA|-_H{F8U z?Qn(@dgJ_C>3+=J$AEtkjrdCNS&DZW;eHkYxh^?nH)08{2b^|VQ4$S%K+rDWLSa?hjR89)*o!k&*lp)pW_tM6|?04Tq5dy@sZJU|n2 z2PrSKTq7sOx3+?uj%J-SlWOY86Z$8)(Yp9lj8{AlK1{_&DdQv^@qhu1;&5&*Y;}$T zKJ-9m_%+w5>+{G!CMJ~JV(u6`_Dzr&vZ9M^t?P;8+SF~u8`TF~XYz3Wn`FaF2S_#r zMSI2mQht`M4r)rUjk{Nk_`&nop6N)7qg#+u%UYvXx0E5=EHA$37F`W0k zgi>~$H7YDn!*EbcIZ80$d?^7x&K!*&*m@f=P^*v^`U&8fmnxzsTqAhQ?CxHz*C0j+ zvK8**Dxam)#ryT2mqe^8Afu_~+BQ0jVIT%5wZhuk`gBAT$)q&`b^n@|`6$NMJJhlP z8K`I@X_rB|I#bx@wmMMGKgQgJ=g%h+^GZSx1S{eRahXbkFtom)%C>E0=sSuSX5>>a zm3~?%nKd09?%h|yzeGn?6h~7L)I6<%N^;+F35zV=z+!X`nRf1gc8%(Z$lnj-?W0ia zI9?F%%R?%rmvno)9Msty__kUS@hR1+{d#_n+laJmY&xviox1e-=~I)O1a$+A`hW+0 zyQ5nlpLAIdWm{Arqpe1=g=k=WH(LVJW;LUWA9iomu53^~nib+HT5#@eMesR;i?wP_ z68LsWtG#QANtcSwLK$BkE*cxBBc@)QT}$kchB}DCn`t`=zj#B=*yy0h#7QCi1SQmk z$mcB$mM2x{fD|*93Vo7k0Tdpx(3sRbKe5FQ8M_sRqO4-4SCH4<+!^b2 zY+OEMomR33zsaJ3M-7*UCUKSK;^N{7KI9xG0Sa9=TrbXV05u@g$e8P9T!+X6bb~ZF zIJf{=mSHv{JK*g3raa>C<%8mnTMf7QVOR8a8z+O_Oj`b^Am1+Y?gr9k=kWdn!|ysC zHP^b9=ajh2YT$CZ28gr?xT?W~Ti$M?4hOAiHIJ8E5kGhse7v?Ym*SVR@}pjROyPa# z3_YigiB*78+aedX)a@yGtu#5&)wVJr3K0ZhHt`h#V41gNzj2Q zm%85TKTeOMKsOp5nfxA__4x?b@&d}W63~)ZqG``QZ9uf+)MN5e+YiH`!QxK pIj^AqeD445+t6|7*&=J1^|{R#NHZen@0;>ztO{{>B!|4je@ literal 0 HcmV?d00001 diff --git a/analytics/twitter-analytics/images/twitter_analytics.png b/src/main/asciidoc/images/twitter_analytics.png similarity index 100% rename from analytics/twitter-analytics/images/twitter_analytics.png rename to src/main/asciidoc/images/twitter_analytics.png diff --git a/src/main/asciidoc/index-docinfo.xml b/src/main/asciidoc/index-docinfo.xml new file mode 100644 index 0000000..8c1b99d --- /dev/null +++ b/src/main/asciidoc/index-docinfo.xml @@ -0,0 +1,27 @@ +Spring Cloud Data Flow Samples +{project-version} + + 2013-2017 + Pivotal Software, Inc. + + + + Copies of this document may be made for your own use and for distribution to + others, provided that you do not charge any fee for such copies and further + provided that each copy contains this Copyright Notice, whether distributed in + print or electronically. + + + + + + + + + Pivotal Software, Inc. + + + + + + diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc new file mode 100644 index 0000000..d602974 --- /dev/null +++ b/src/main/asciidoc/index.adoc @@ -0,0 +1,35 @@ += Spring Cloud Data Flow Samples +Sabby Anandan; David Turanski; Glenn Renfro; Eric Bottard; Mark Pollack; +:doctype: book +:toc: +:toclevels: 4 +:source-highlighter: prettify +:numbered: +:icons: font +:hide-uri-scheme: +:docinfo: shared + +:spring-cloud-stream-docs: http://docs.spring.io/spring-cloud-stream/docs/{scst-core-version}/reference/htmlsingle/index.html +:github-code: https://github.com/spring-cloud/spring-cloud-dataflow-samples + + +ifdef::backend-html5[] + +Version {project-version} + +(C) 2012-2017 Pivotal Software, Inc. + +_Copies of this document may be made for your own use and for distribution to +others, provided that you do not charge any fee for such copies and further +provided that each copy contains this Copyright Notice, whether distributed in +print or electronically._ + +endif::backend-html5[] + +// ====================================================================================== + +[[overview]] + +include::overview.adoc[] + +// ====================================================================================== diff --git a/src/main/asciidoc/local-server.adoc b/src/main/asciidoc/local-server.adoc new file mode 100644 index 0000000..759b20a --- /dev/null +++ b/src/main/asciidoc/local-server.adoc @@ -0,0 +1,9 @@ + +The Local Data Flow Server is Spring Boot application available for http://cloud.spring.io/spring-cloud-dataflow/#platform-implementations[download] or you can https://github.com/spring-cloud/spring-cloud-dataflow[build] it yourself. +If you build it yourself, the executable jar will be in `spring-cloud-dataflow-server-local/target` + +To run the Local Data Flow server Open a new terminal session: +``` +$cd +$java -jar spring-cloud-dataflow-server-local-.jar +``` diff --git a/src/main/asciidoc/maven-access.adoc b/src/main/asciidoc/maven-access.adoc new file mode 100644 index 0000000..d8214a5 --- /dev/null +++ b/src/main/asciidoc/maven-access.adoc @@ -0,0 +1,7 @@ +NOTE: These samples assume that the Data Flow Server can access a remote Maven repository, `https://repo.spring.io/libs-release` by default. If your Data Flow server is running behind a firewall, or you are using a maven proxy preventing +access to public repositories, you will need to install the sample apps in your internal Maven repository and https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started-maven-configuration[configure] +the server accordingly. The sample applications are typically registered using Data Flow's bulk import facility. For example, the Shell command `dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven` (The actual URI is release and binder specific so refer to the sample instructions for the actual URL). +The bulk import URI references a plain text file containing entries for all of the publicly available Spring Cloud Stream and Task applications published to `https://repo.spring.io`. For example, +`source.http=maven://org.springframework.cloud.stream.app:http-source-rabbit:1.2.0.RELEASE` registers the `http` source app at the corresponding Maven address, relative to the remote repository(ies) configured for the +Data Flow server. The format is `maven://::` You will need to https://repo.spring.io/libs-release/org/springframework/cloud/stream/app/spring-cloud-stream-app-descriptor/Bacon.RELEASE/spring-cloud-stream-app-descriptor-Bacon.RELEASE.rabbit-apps-maven-repo-url.properties[download] the required apps or https://github.com/spring-cloud-stream-app-starters[build] them and then install them in your Maven repository, using whatever group, artifact, and version you choose. If you do +this, register individual apps using `dataflow:>app register...` using the `maven://` resource URI format corresponding to your installed app. diff --git a/src/main/asciidoc/overview.adoc b/src/main/asciidoc/overview.adoc new file mode 100644 index 0000000..1eb7288 --- /dev/null +++ b/src/main/asciidoc/overview.adoc @@ -0,0 +1,23 @@ +[[spring-cloud-data-flow-samples-overview]] +== Overview +This guide contains samples and demonstrations of how to build data pipelines with https://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow]. + +== Streaming +include::streaming/cassandra/http-to-cassandra/main.adoc[] +include::streaming/jdbc/http-mysql/main.adoc[] +include::streaming/gemfire/http-gemfire/main.adoc[] +include::streaming/gemfire/gemfire-cq-log/main.adoc[] +include::streaming/gemfire/gemfire-log/main.adoc[] +include::streaming/custom-apps/celsius-converter-processor/main.adoc[] + +== Task / Batch +include::tasks/simple-batch-job/main.adoc[] + +== Analytics +include::analytics/twitter-analytics/main.adoc[] + +== Data Science +include::datascience/species-prediction/main.adoc[] + +== Functions +include::functions/main.adoc[] diff --git a/src/main/asciidoc/shell.adoc b/src/main/asciidoc/shell.adoc new file mode 100644 index 0000000..6d0724f --- /dev/null +++ b/src/main/asciidoc/shell.adoc @@ -0,0 +1,30 @@ + +The Spring Cloud Data Flow Shell is available for https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started-deploying-spring-cloud-dataflow[download] or you can https://github.com/spring-cloud/spring-cloud-dataflow[build] it yourself. + +NOTE: the Spring Cloud Data Flow Shell and Local server implementation are in the same repository and are both built by running `./mvnw install` from the project root directory. If you have already run the build, use the jar in `spring-cloud-dataflow-shell/target` + +To run the Shell open a new terminal session: +``` +$ cd +$ java -jar spring-cloud-dataflow-shell-.jar + ____ ____ _ __ + / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | + \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | + ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | + |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| + ____ |_| _ __|___/ __________ + | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ + | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ + | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / + |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ + + +Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". +dataflow:> +``` +NOTE: The Spring Cloud Data Flow Shell is a Spring Boot application that connects to the Data Flow Server’s REST API and supports a DSL that simplifies the process of defining a stream or task and managing its lifecycle. Most of these samples +use the shell. If you prefer, you can use the Data Flow UI http://localhost:9393/dashboard, (or wherever it the server is hosted) to perform equivalent operations. + +ifdef::backend-pdf[] +image::scdf-dashboard.png[SCDF Dashboard, scaledwidth="50%"] +endif::[] diff --git a/src/main/asciidoc/streaming/cassandra/http-to-cassandra/local.adoc b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/local.adoc new file mode 100644 index 0000000..2012b00 --- /dev/null +++ b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/local.adoc @@ -0,0 +1,78 @@ +[[http-cassandra-local]] +==== Using the Local Server + +===== Additional Prerequisites + +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] + +* Running instance of link:http://kafka.apache.org/downloads.html[Kafka] +* Running instance of link:http://cassandra.apache.org/[Apache Cassandra] + +* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] to connect to the Cassandra instance. You might have to provide `host`, `port`, `username` and `password` depending on the Cassandra configuration you are using. +* Create a keyspace and a `book` table in Cassandra using: + +``` +CREATE KEYSPACE clouddata WITH REPLICATION = { 'class' : 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1' } AND DURABLE_WRITES = true; +USE clouddata; +CREATE TABLE book ( + id uuid PRIMARY KEY, + isbn text, + author text, + title text +); +``` + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Kafka binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven +``` ++ +. Create the stream ++ +``` +dataflow:>stream create cassandrastream --definition "http --server.port=8888 --spring.cloud.stream.bindings.output.contentType='application/json' | cassandra --ingestQuery='insert into book (id, isbn, title, author) values (uuid(), ?, ?, ?)' --keyspace=clouddata" --deploy + +Created and deployed new stream 'cassandrastream' +``` +NOTE: If Cassandra isn't running on default port on `localhost` or if you need username and password to connect, use one of the following options to specify the necessary connection parameters: `--username='' --password='' --port= --contact-points=` + ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Notice that `cassandrastream-http` and `cassandrastream-cassandra` link:https://github.com/spring-cloud-stream-app-starters//[Spring Cloud Stream] applications are running as Spring Boot applications within the `server` as a collocated process. ++ + +[source,console,options=nowrap] +---- +2015-12-15 15:52:31.576 INFO 18337 --- [nio-9393-exec-1] o.s.c.d.a.s.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:cassandra-sink:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 + Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-284240942697761420/cassandrastream.cassandra +2015-12-15 15:52:31.583 INFO 18337 --- [nio-9393-exec-1] o.s.c.d.a.s.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:http-source:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 + Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-284240942697761420/cassandrastream.http +---- ++ +. Post sample data pointing to the `http` endpoint: `http://localhost:8888` (`8888` is the `server.port` we specified for the `http` source in this case) ++ +``` +dataflow:>http post --contentType 'application/json' --data '{"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"}' --target http://localhost:8888 +> POST (application/json;charset=UTF-8) http://localhost:8888 {"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"} +> 202 ACCEPTED +``` ++ +. Connect to the Cassandra instance and query the table `clouddata.book` to list the persisted records ++ +``` +select * from clouddata.book; +``` + ++ +. You're done! diff --git a/src/main/asciidoc/streaming/cassandra/http-to-cassandra/main.adoc b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/main.adoc new file mode 100644 index 0000000..b446885 --- /dev/null +++ b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/main.adoc @@ -0,0 +1,25 @@ +[[spring-cloud-data-flow-samples-http-cassandra-overview]] +:sectnums: +:docs_dir: ../../.. +=== HTTP to Cassandra Demo + +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from an _HTTP_ endpoint and write the payload to a _Cassandra_ database. + +We will take you through the steps to configure and Spring Cloud Data Flow server in either a https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started/[local] or https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#getting-started[Cloud Foundry] environment. + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] + +include::local.adoc[] + +include::pcf.adoc[] + +==== Summary + +In this sample, you have learned: + +* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers +* How to use Spring Cloud Data Flow's `shell` +* How to create streaming data pipeline to connect and write to `Cassandra` +* How to scale applications on `Pivotal Cloud Foundry` diff --git a/src/main/asciidoc/streaming/cassandra/http-to-cassandra/pcf.adoc b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/pcf.adoc new file mode 100644 index 0000000..05e44af --- /dev/null +++ b/src/main/asciidoc/streaming/cassandra/http-to-cassandra/pcf.adoc @@ -0,0 +1,99 @@ +[[http-cassandra-cf]] +==== Using the Cloud Foundry Server + +===== Additional Prerequisites + +* Cloud Foundry instance +* A `rabbit` service instance + +* A Running instance of `cassandra` in Cloud Foundry or from another Cloud provider +* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] to connect to the Cassandra instance. You might have to provide `host`, `port`, `username` and `password` depending on the Cassandra configuration you are using. +* Create a `book` table in your Cassandra keyspace using: ++ +``` +CREATE TABLE book ( + id uuid PRIMARY KEY, + isbn text, + author text, + title text +); +``` +* The Spring Cloud Data Flow Cloud Foundry Server +include::{docs_dir}/cloudfoundry-server.adoc[] + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Create the stream ++ + +``` +dataflow:>stream create cassandrastream --definition "http --spring.cloud.stream.bindings.output.contentType='application/json' | cassandra --ingestQuery='insert into book (id, isbn, title, author) values (uuid(), ?, ?, ?)' --username='' --password='' --port= --contact-points= --keyspace=''" --deploy + +Created and deployed new stream 'cassandrastream' +``` ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Notice that `cassandrastream-http` and `cassandrastream-cassandra` https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as _cloud-native_ (microservice) applications in Cloud Foundry ++ + +``` +$ cf apps +Getting apps in org [your-org] / space [your-space] as user... +OK + +name requested state instances memory disk urls +cassandrastream-cassandra started 1/1 1G 1G cassandrastream-cassandra.app.io +cassandrastream-http started 1/1 1G 1G cassandrastream-http.app.io +dataflow-server started 1/1 1G 1G dataflow-server.app.io +``` ++ +. Lookup the `url` for `cassandrastream-http` application from the list above. Post sample data pointing to the `http` endpoint: `` ++ +``` +http post --contentType 'application/json' --data '{"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"}' --target http:// +> POST (application/json;charset=UTF-8) http://cassandrastream-http.app.io {"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"} +> 202 ACCEPTED +``` ++ +. Connect to the Cassandra instance and query the table `book` to list the data inserted ++ +``` +select * from book; +``` + ++ +. Now, let's try to take advantage of Pivotal Cloud Foundry's platform capability. Let's scale the `cassandrastream-http` application from 1 to 3 instances ++ +``` +$ cf scale cassandrastream-http -i 3 +Scaling app cassandrastream-http in org user-dataflow / space development as user... +OK +``` ++ +. Verify App instances (3/3) running successfully ++ +``` +$ cf apps +Getting apps in org user-dataflow / space development as user... +OK + +name requested state instances memory disk urls +cassandrastream-cassandra started 1/1 1G 1G cassandrastream-cassandra.app.io +cassandrastream-http started 3/3 1G 1G cassandrastream-http.app.io +dataflow-server started 1/1 1G 1G dataflow-server.app.io +``` ++ +. You're done! diff --git a/src/main/asciidoc/streaming/custom-apps/celsius-converter-processor/main.adoc b/src/main/asciidoc/streaming/custom-apps/celsius-converter-processor/main.adoc new file mode 100644 index 0000000..681b788 --- /dev/null +++ b/src/main/asciidoc/streaming/custom-apps/celsius-converter-processor/main.adoc @@ -0,0 +1,161 @@ +[[spring-cloud-data-flow-samples-custom-application-overview]] +:sectnums: +:docs_dir: ../../.. + +=== Custom Spring Cloud Stream Processor + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] +* A Java IDE +* https://maven.apache.org/[Maven] Installed +* A running instance of https://www.rabbitmq.com/[Rabbit MQ] + +==== Creating the Custom Stream App +We will create a custom https://cloud.spring.io/spring-cloud-stream/[Spring Cloud Stream] application and run it on Spring Cloud Data Flow. +We'll go through the steps to make a simple processor that converts temperature from Fahrenheit to Celsius. +We will be running the demo locally, but all the steps will work in a Cloud Foundry environment as well. + +. Create a new spring cloud stream project ++ +* Create a http://start.spring.io/[Spring initializer] project + +* Set the group to `demo.celsius.converter` and the artifact name as `celsius-converter-processor` + +* Choose a message transport binding as a dependency for the custom app +There are options for choosing `Rabbit MQ` or `Kafka` as the message transport. +For this demo, we will use `rabbit`. Type _rabbit_ in the search bar under _Search for dependencies_ and select `Stream Rabbit`. + +* Hit the generate project button and open the new project in an IDE of your choice ++ +. Develop the app ++ +We can now create our custom app. Our Spring Cloud Stream application is a Spring Boot application that runs as an executable jar. The application will include two Java classes: + +* `CelsiusConverterProcessorAplication.java` - the main Spring Boot application class, generated by Spring initializr + +* `CelsiusConverterProcessorConfiguration.java` - the Spring Cloud Stream code that we will write ++ +We are creating a transformer that takes a Fahrenheit input and converts it to Celsius. +Following the same naming convention as the application file, create a new Java class in the same package called `CelsiusConverterProcessorConfiguration.java`. ++ +.CelsiusConverterProcessorConfiguration.java +[source,java] +``` +@EnableBinding(Processor.class) +public class CelsiusConverterProcessorConfiguration { + + @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) + public int convertToCelsius(String payload) { + int fahrenheitTemperature = Integer.parseInt(payload); + return (farenheitTemperature-32)*5/9; + } +} +``` ++ +Here we introduced two important Spring annotations. +First we annotated the class with `@EnableBinding(Processor.class)`. +Second we created a method and annotated it with `@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)`. +By adding these two annotations we have configured this stream app as a `Processor` (as opposed to a `Source` or a `Sink`). +This means that the application receives input from an upstream application via the `Processor.INPUT` channel and sends its output to a downstream application via the `Processor.OUTPUT` channel. ++ +The `convertToCelsius` method takes a `String` as input for Fahrenheit and then returns the converted Celsius as an integer. +This method is very simple, but that is also the beauty of this programming style. +We can add as much logic as we want to this method to enrich this processor. +As long as we annotate it properly and return valid output, it works as a Spring Cloud Stream Processor. Also note that it is straightforward to unit test this code. ++ +. Build the Spring Boot application with Maven ++ +``` +$cd +$./mvnw clean package +``` ++ +. Run the Application standalone ++ +``` +java -jar target/celsius-converter-processor-0.0.1-SNAPSHOT.jar +``` ++ +If all goes well, we should have a running standalone Spring Boot Application. +Once we verify that the app is started and running without any errors, we can stop it. + +==== Deploying the App to Spring Cloud Data Flow + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Register the custom processor ++ +``` +app register --type processor --name convertToCelsius --uri --force +``` ++ +. Create the stream ++ +We will create a stream that uses the out of the box `http` source and `log` sink and our custom transformer. ++ +``` +dataflow:>stream create --name convertToCelsiusStream --definition "http --port=9090 | convertToCelsius | log" --deploy + +Created and deployed new stream 'convertToCelsiusStream' +``` ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Verify that the apps have successfully deployed ++ +``` +dataflow:>runtime apps +``` ++ +.Note the file location of the application logs ++ +[source,console,options=nowrap] +---- +2016-09-27 10:03:11.988 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.log instance 0 + Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984991968/convertToCelsiusStream.log +2016-09-27 10:03:12.397 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.convertToCelsius instance 0 + Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984992392/convertToCelsiusStream.convertToCelsius +2016-09-27 10:03:14.445 INFO 95234 --- [nio-9393-exec-9] o.s.c.d.spi.local.LocalAppDeployer : deploying app convertToCelsiusStream.http instance 0 + Logs will be in /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-3236898888473815319/convertToCelsiusStream-1474984994440/convertToCelsiusStream.http +---- ++ +. Post sample data to the `http` endpoint: `http://localhost:9090` (`9090` is the `port` we specified for the `http` source in this case) ++ + +``` +dataflow:>http post --target http://localhost:9090 --data 76 +> POST (text/plain;Charset=UTF-8) http://localhost:9090 76 +> 202 ACCEPTED +``` ++ +. Open the log file for the `convertToCelsiusStream.log` app to see the output of our stream ++ +[source,console,options=nowrap] +---- +tail -f /var/folders/2q/krqwcbhj2d58csmthyq_n1nw0000gp/T/spring-cloud-dataflow-7563139704229890655/convertToCelsiusStream-1474990317406/convertToCelsiusStream.log/stdout_0.log +---- ++ +You should see the temperature you posted converted to Celsius! +``` +2016-09-27 10:05:34.933 INFO 95616 --- [CelsiusStream-1] log.sink : 24 +``` + +==== Summary +In this sample, you have learned: + +* How to write a custom `Processor` stream application +* How to use Spring Cloud Data Flow's `Local` server +* How to use Spring Cloud Data Flow's `shell` application diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/local.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/local.adoc new file mode 100644 index 0000000..c169989 --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/local.adoc @@ -0,0 +1,91 @@ +[[gemfire-cq-log-local]] +==== Using the Local Server +===== Additional Prerequisites +* A Running Data Flow Server +include::{docs_dir}/local-server.adoc[] +* A running instance of https://www.rabbitmq.com[Rabbit MQ] + +===== Building and Running the Demo + +. Use gfsh to start a locator and server ++ +``` +gfsh>start locator --name=locator1 +gfsh>start server --name=server1 + +``` +. Create a region called `Orders` ++ +``` +gfsh>create region --name Orders --type=REPLICATE +``` ++ +*Use the Shell to create the sample stream* ++ +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` +. Create the stream ++ +This example creates an gemfire-cq source to which will publish events matching a query criteria on a region. In this case we will monitor the `Orders` region. For simplicity, we will avoid creating a data structure for the order. +Each cache entry contains an integer value representing the quantity of the ordered item. This stream will fire a message whenever the value>999. By default, the source emits only the value. Here we will override that using the +`cq-event-expression` property. This accepts a SpEL expression bound to a https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/query/CqEvent.html[CQEvent]. To reference the entire CQEvent instace, we use `#this`. +In order to display the contents in the log, we will invoke `toString()` on the instance. ++ +``` +dataflow:>stream create --name orders --definition " gemfire-cq --query='SELECT * from /Orders o where o > 999' --cq-event-expression=#this.toString() | log" --deploy +Created and deployed new stream 'events' +``` +NOTE: If the Geode locator isn't running on default port on `localhost`, add the options `--connect-type=locator --host-addresses=:`. If there are multiple +locators, you can provide a comma separated list of locator addresses. This is not necessary for the sample but is typical for production environments to enable fail-over. + +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` + +. Monitor stdout for the log sink. When you deploy the stream, you will see log messages in the Data Flow server console like this ++ +``` +2017-10-30 09:39:36.283 INFO 8167 --- [nio-9393-exec-5] o.s.c.d.spi.local.LocalAppDeployer : Deploying app with deploymentId orders.log instance 0. + Logs will be in /var/folders/hd/5yqz2v2d3sxd3n879f4sg4gr0000gn/T/spring-cloud-dataflow-5375107584795488581/orders-1509370775940/orders.log +``` ++ +Copy the location of the `log` sink logs. This is a directory that ends in `orders.log`. The log files will be in `stdout_0.log` under this directory. You can monitor the output of the log sink using `tail`, or something similar: ++ +``` +$tail -f /var/folders/hd/5yqz2v2d3sxd3n879f4sg4gr0000gn/T/spring-cloud-dataflow-5375107584795488581/orders-1509370775940/orders.log/stdout_0.log +``` ++ +. Using `gfsh`, create and update some cache entries ++ +``` +gfsh>put --region Orders --value-class java.lang.Integer --key 01234 --value 1000 +gfsh>put --region Orders --value-class java.lang.Integer --key 11234 --value 1005 +gfsh>put --region Orders --value-class java.lang.Integer --key 21234 --value 100 +gfsh>put --region Orders --value-class java.lang.Integer --key 31234 --value 999 +gfsh>put --region Orders --value-class java.lang.Integer --key 21234 --value 1000 + +``` ++ +. Observe the log output +You should see messages like: ++ +``` +2017-10-30 09:53:02.231 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=CREATE; cq operation=CREATE; key=01234; value=1000] +2017-10-30 09:53:19.732 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=CREATE; cq operation=CREATE; key=11234; value=1005] +2017-10-30 09:53:53.242 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=UPDATE; cq operation=CREATE; key=21234; value=1000] +``` ++ +. Another interesting demonstration combines `gemfire-cq` with the link::../http-gemfire/README.adoc[http-gemfire] example. +``` +dataflow:> stream create --name stocks --definition "http --port=9090 | gemfire-json-server --regionName=Stocks --keyExpression=payload.getField('symbol')" --deploy +dataflow:> stream create --name stock_watch --definition "gemfire-cq --query='Select * from /Stocks where symbol=''VMW''' | log" --deploy +``` + +. You're done! diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/main.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/main.adoc new file mode 100644 index 0000000..0591be0 --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/main.adoc @@ -0,0 +1,31 @@ +[[spring-cloud-data-flow-samples-gemfire-cq-log-overview]] +:sectnums: +:docs_dir: ../../.. + +=== Gemfire CQ to Log Demo + +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from a `gemfire-cq` (Continuous Query) endpoint and write to a log using the `log` sink. +The `gemfire-cq` source creates a Continuous Query to monitor events for a region that match the query's result set and publish a message whenever such an event is emitted. In this example, we simulate monitoring orders to trigger a process whenever +the quantity ordered is above a defined limit. + +We will take you through the steps to configure and run Spring Cloud Data Flow server in either a https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started/[local] or https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#getting-started[Cloud Foundry] environment. + +NOTE: For legacy reasons the `gemfire` Spring Cloud Stream Apps are named after `Pivotal GemFire`. The code base for the commercial product has since been open sourced as `Apache Geode`. These samples should work with compatible versions of Pivotal GemFire or Apache Geode. Herein we will refer to the installed IMDG simply as `Geode`. + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A Geode installation with a locator and cache server running +include::{docs_dir}/geode-setup.adoc[] + +include::local.adoc[] + +include::pcf.adoc[] + +==== Summary + +In this sample, you have learned: + +* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers +* How to use Spring Cloud Data Flow's `shell` +* How to create streaming data pipeline to connect and publish CQ events from `gemfire` diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/pcf.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/pcf.adoc new file mode 100644 index 0000000..a895586 --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-cq-log/pcf.adoc @@ -0,0 +1,114 @@ +[[gemfire-cq-log-cf]] +==== Using the Cloud Foundry Server +===== Additional Prerequisites + +* A Cloud Foundry instance + +* Running instance of a `rabbit` service in Cloud Foundry + +* Running instance of the https://docs.pivotal.io/p-cloud-cache/1-0/developer.html[Pivotal Cloud Cache for PCF] (PCC) service `cloudcache` in Cloud Foundry. + +* The Spring Cloud Data Flow Cloud Foundry Server + +include::{docs_dir}/cloudfoundry-server.adoc[] + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Get the PCC connection information ++ +``` +$ cf service-key cloudcache my-service-key +Getting key my-service-key for service instance cloudcache as ... + +{ + "locators": [ + "10.0.16.9[55221]", + "10.0.16.11[55221]", + "10.0.16.10[55221]" + ], + "urls": { + "gfsh": "http://...", + "pulse": "http://.../pulse" + }, + "users": [ + { + "password": , + "username": "cluster_operator" + }, + { + "password": , + "username": "developer" + } + ] +} +``` ++ +. Using `gfsh`, connect to the PCC instance as `cluster_operator` using the service key values and create the Test region. ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>create region --name Orders --type=REPLICATE +``` ++ +. Create the stream using the Data Flow Shell ++ +This example creates an gemfire-cq source to which will publish events matching a query criteria on a region. In this case we will monitor the `Orders` region. For simplicity, we will avoid creating a data structure for the order. +Each cache entry contains an integer value representing the quantity of the ordered item. This stream will fire a message whenever the value>999. By default, the source emits only the value. Here we will override that using the +`cq-event-expression` property. This accepts a SpEL expression bound to a https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/query/CqEvent.html[CQEvent]. To reference the entire CQEvent instance, we use `#this`. +In order to display the contents in the log, we will invoke `toString()` on the instance. ++ +``` +dataflow:>stream create --name orders --definition " gemfire-cq --username=developer --password= --connect-type=locator --host-addresses=10.0.16.9:55221 --query='SELECT * from /Orders o where o > 999' --cq-event-expression=#this.toString() | log" --deploy +Created and deployed new stream 'events' +``` ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Monitor stdout for the log sink ++ +``` +cf logs +``` ++ +. Using `gfsh`, create and update some cache entries ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>put --region Orders --value-class java.lang.Integer --key 01234 --value 1000 +gfsh>put --region Orders --value-class java.lang.Integer --key 11234 --value 1005 +gfsh>put --region Orders --value-class java.lang.Integer --key 21234 --value 100 +gfsh>put --region Orders --value-class java.lang.Integer --key 31234 --value 999 +gfsh>put --region Orders --value-class java.lang.Integer --key 21234 --value 1000 + +``` ++ +. Observe the log output +You should see messages like: ++ +[source,console,options=nowrap] +---- +2017-10-30 09:53:02.231 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=CREATE; cq operation=CREATE; key=01234; value=1000] +2017-10-30 09:53:19.732 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=CREATE; cq operation=CREATE; key=11234; value=1005] +2017-10-30 09:53:53.242 INFO 8563 --- [ire-cq.orders-1] log-sink : CqEvent [CqName=GfCq1; base operation=UPDATE; cq operation=CREATE; key=21234; value=1000] +---- ++ +. Another interesting demonstration combines `gemfire-cq` with the link:../http-gemfire/README.adoc[http-gemfire] example. ++ +``` +dataflow:> stream create --name stocks --definition "http --port=9090 | gemfire-json-server --regionName=Stocks --keyExpression=payload.getField('symbol')" --deploy +dataflow:> stream create --name stock_watch --definition "gemfire-cq --query='Select * from /Stocks where symbol=''VMW''' | log" --deploy +``` ++ +. You're done! diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-log/local.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-log/local.adoc new file mode 100644 index 0000000..48722ac --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-log/local.adoc @@ -0,0 +1,106 @@ +[[gemfire-log-local]] +==== Using the Local Server +===== Additional Prerequisites + +* A Running Data Flow Server +include::{docs_dir}/local-server.adoc[] +* A running instance of https://www.rabbitmq.com[Rabbit MQ] + +===== Building and Running the Demo + +. Use gfsh to start a locator and server ++ +``` +gfsh>start locator --name=locator1 +gfsh>start server --name=server1 + +``` +. Create a region called `Test` ++ +``` +gfsh>create region --name Test --type=REPLICATE +``` ++ +*Use the Shell to create the sample stream* ++ +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` +. Create the stream ++ +This example creates an gemfire source to which will publish events on a region ++ +``` +dataflow:>stream create --name events --definition " gemfire --regionName=Test | log" --deploy +Created and deployed new stream 'events' +``` +NOTE: If the Geode locator isn't running on default port on `localhost`, add the options `--connect-type=locator --host-addresses=:`. If there are multiple +locators, you can provide a comma separated list of locator addresses. This is not necessary for the sample but is typical for production environments to enable fail-over. + +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` + +. Monitor stdout for the log sink. When you deploy the stream, you will see log messages in the Data Flow server console like this ++ + +[source,console,options=nowrap] +---- +2017-10-28 17:28:23.275 INFO 15603 --- [nio-9393-exec-2] o.s.c.d.spi.local.LocalAppDeployer : Deploying app with deploymentId events.log instance 0. + Logs will be in /var/folders/hd/5yqz2v2d3sxd3n879f4sg4gr0000gn/T/spring-cloud-dataflow-4093992067314402881/events-1509226103269/events.log +2017-10-28 17:28:23.277 INFO 15603 --- [nio-9393-exec-2] o.s.c.d.s.c.StreamDeploymentController : Downloading resource URI [maven://org.springframework.cloud.stream.app:gemfire-source-rabbit:1.2.0.RELEASE] +2017-10-28 17:28:23.311 INFO 15603 --- [nio-9393-exec-2] o.s.c.d.s.c.StreamDeploymentController : Deploying application named [gemfire] as part of stream named [events] with resource URI [maven://org.springframework.cloud.stream.app:gemfire-source-rabbit:1.2.0.RELEASE] +2017-10-28 17:28:23.318 INFO 15603 --- [nio-9393-exec-2] o.s.c.d.spi.local.LocalAppDeployer : Deploying app with deploymentId events.gemfire instance 0. + Logs will be in /var/folders/hd/5yqz2v2d3sxd3n879f4sg4gr0000gn/T/spring-cloud-dataflow-4093992067314402881/events-1509226103311/events.gemfire +---- + ++ +Copy the location of the `log` sink logs. This is a directory that ends in `events.log`. The log files will be in `stdout_0.log` under this directory. You can monitor the output of the log sink using `tail`, or something similar: ++ + +[source,console,options=nowrap] +---- +$tail -f /var/folders/hd/5yqz2v2d3sxd3n879f4sg4gr0000gn/T/spring-cloud-dataflow-4093992067314402881/events-1509226103269/events.log/stdout_0.log +---- + ++ +. Using `gfsh`, create and update some cache entries ++ +``` +gfsh>put --region /Test --key 1 --value "value 1" +gfsh>put --region /Test --key 2 --value "value 2" +gfsh>put --region /Test --key 3 --value "value 3" +gfsh>put --region /Test --key 1 --value "new value 1" +``` ++ +. Observe the log output +You should see messages like: ++ +[source,console,options=nowrap] +---- +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 1" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 2" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 3" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : new value 1" +---- + ++ +By default, the message payload contains the updated value. Depending on your application, you may need additional information. The data comes from https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/EntryEvent.html[EntryEvent]. You +can access any fields using the source's `cache-event-expression` property. This takes a SpEL expression bound to the EntryEvent. Try something like `--cache-event-expression='{key:'\+key+',new_value:'\+newValue+'}'` (HINT: You will need to destroy the stream and recreate it to +add this property, an exercise left to the reader). Now you should see log messages like: ++ + +[source,console,options=nowrap] +---- +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log-sink : {key:1,new_value:value 1} +2017-10-28 17:41:24.466 INFO 18986 --- [emfire.events-1] log-sink : {key:2,new_value:value 2} +---- + ++ +. You're done! diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-log/main.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-log/main.adoc new file mode 100644 index 0000000..530c14b --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-log/main.adoc @@ -0,0 +1,30 @@ +[[spring-cloud-data-flow-samples-gemfire-log-overview]] +:sectnums: +:docs_dir: ../../.. + +=== Gemfire to Log Demo + +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from a `gemfire` endpoint and write to a log using the `log` sink. +The `gemfire` source creates a https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/CacheListener.html[CacheListener] to monitor events for a region and publish a message whenever an entry is changed. + +We will take you through the steps to configure and run Spring Cloud Data Flow server in either a https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started/[local] or https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#getting-started[Cloud Foundry] environment. + +NOTE: For legacy reasons the `gemfire` Spring Cloud Stream Apps are named after `Pivotal GemFire`. The code base for the commercial product has since been open sourced as `Apache Geode`. These samples should work with compatible versions of Pivotal GemFire or Apache Geode. Herein we will refer to the installed IMDG simply as `Geode`. + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A Geode installation with a locator and cache server running +include::{docs_dir}/geode-setup.adoc[] + +include::local.adoc[] + +include::pcf.adoc[] + +==== Summary + +In this sample, you have learned: + +* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers +* How to use Spring Cloud Data Flow's `shell` +* How to create streaming data pipeline to connect and publish events from `gemfire` diff --git a/src/main/asciidoc/streaming/gemfire/gemfire-log/pcf.adoc b/src/main/asciidoc/streaming/gemfire/gemfire-log/pcf.adoc new file mode 100644 index 0000000..288bf0d --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/gemfire-log/pcf.adoc @@ -0,0 +1,110 @@ +[[gemfire-log-cf]] +==== Using the Cloud Foundry Server +===== Additional Prerequisites +* A Cloud Foundry instance + +* Running instance of a `rabbit` service in Cloud Foundry + +* Running instance of the https://docs.pivotal.io/p-cloud-cache/1-0/developer.html[Pivotal Cloud Cache for PCF] (PCC) service `cloudcache` in Cloud Foundry. + +* The Spring Cloud Data Flow Cloud Foundry Server + +include::{docs_dir}/cloudfoundry-server.adoc[] + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Get the PCC connection information ++ +``` +$ cf service-key cloudcache my-service-key +Getting key my-service-key for service instance cloudcache as ... + +{ + "locators": [ + "10.0.16.9[55221]", + "10.0.16.11[55221]", + "10.0.16.10[55221]" + ], + "urls": { + "gfsh": "http://...", + "pulse": "http://.../pulse" + }, + "users": [ + { + "password": , + "username": "cluster_operator" + }, + { + "password": , + "username": "developer" + } + ] +} +``` ++ +. Using `gfsh`, connect to the PCC instance as `cluster_operator` using the service key values and create the Test region. ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>create region --name Test --type=REPLICATE +``` ++ +. Create the stream, connecting to the PCC instance as developer. This example creates an gemfire source to which will publish events on a region ++ +``` +dataflow stream create --name events --definition " gemfire --username=developer --password= --connect-type=locator --host-addresses=10.0.16.9:55221 --regionName=Test | log" --deploy +``` + +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Monitor stdout for the log sink ++ +``` +cf logs +``` ++ +. Using `gfsh`, create and update some cache entries ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>put --region /Test --key 1 --value "value 1" +gfsh>put --region /Test --key 2 --value "value 2" +gfsh>put --region /Test --key 3 --value "value 3" +gfsh>put --region /Test --key 1 --value "new value 1" +``` ++ +. Observe the log output ++ +You should see messages like: ++ +[source,console,options=nowrap] +---- +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 1" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 2" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : value 3" +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log sink : new value 1" +---- ++ +By default, the message payload contains the updated value. Depending on your application, you may need additional information. The data comes from https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/EntryEvent.html[EntryEvent]. You +can access any fields using the source's `cache-event-expression` property. This takes a SpEL expression bound to the EntryEvent. Try something like `--cache-event-expression='{key:'\+key+',new_value:'\+newValue+'}'` (HINT: You will need to destroy the stream and recreate it to +add this property, an exercise left to the reader). Now you should see log messages like: ++ +[source,console,options=nowrap] +---- +2017-10-28 17:28:52.893 INFO 18986 --- [emfire.events-1] log-sink : {key:1,new_value:value 1} +2017-10-28 17:41:24.466 INFO 18986 --- [emfire.events-1] log-sink : {key:2,new_value:value 2} +---- ++ +. You're done! diff --git a/src/main/asciidoc/streaming/gemfire/http-gemfire/local.adoc b/src/main/asciidoc/streaming/gemfire/http-gemfire/local.adoc new file mode 100644 index 0000000..cd3ae4b --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/http-gemfire/local.adoc @@ -0,0 +1,78 @@ +[[gemfire-http-local]] +==== Using the Local Server +===== Additional Prerequisites + +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] +* A running instance of https://www.rabbitmq.com[Rabbit MQ] + +===== Building and Running the Demo + +. Use gfsh to start a locator and server ++ +``` +gfsh>start locator --name=locator1 +gfsh>start server --name=server1 + +``` +. Create a region called `Stocks` ++ +``` +gfsh>create region --name Stocks --type=REPLICATE +``` ++ +*Use the Shell to create the sample stream* ++ +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` +. Create the stream ++ +This example creates an http endpoint to which we will post stock prices as a JSON document containing `symbol` and `price` fields. +The property `--json=true` to enable Geode's JSON support and configures the sink to convert JSON String payloads to https://geode.apache.org/releases/latest/javadoc/org/apache/geode/pdx/PdxInstance.html[PdxInstance], the recommended way +to store JSON documents in Geode. The `keyExpression` property is a SpEL expression used to extract the `symbol` value the PdxInstance to use as an entry key. ++ +NOTE: PDX serialization is very efficient and supports OQL queries without requiring a custom domain class. +Use of custom domain types requires these classes to be in the class path of both the stream apps and the cache server. +For this reason, the use of custom payload types is generally discouraged. ++ +``` +dataflow:>stream create --name stocks --definition "http --port=9090 | gemfire --json=true --regionName=Stocks --keyExpression=payload.getField('symbol')" --deploy +Created and deployed new stream 'stocks' +``` +NOTE: If the Geode locator isn't running on default port on `localhost`, add the options `--connect-type=locator --host-addresses=:`. If there are multiple +locators, you can provide a comma separated list of locator addresses. This is not necessary for the sample but is typical for production environments to enable fail-over. + +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` + +. Post sample data pointing to the `http` endpoint: `http://localhost:9090` (`9090` is the `port` we specified for the `http` source) ++ +``` +dataflow:>http post --target http://localhost:9090 --contentType application/json --data '{"symbol":"VMW","price":117.06}' +> POST (application/json) http://localhost:9090 {"symbol":"VMW","price":117.06} +> 202 ACCEPTED +``` ++ +. Using `gfsh`, connect to the locator if not already connected, and verify the cache entry was created. ++ +``` +gfsh>get --key='VMW' --region=/Stocks +Result : true +Key Class : java.lang.String +Key : VMW +Value Class : org.apache.geode.pdx.internal.PdxInstanceImpl + +symbol | price +------ | ------ +VMW | 117.06 +``` ++ +. You're done! diff --git a/src/main/asciidoc/streaming/gemfire/http-gemfire/main.adoc b/src/main/asciidoc/streaming/gemfire/http-gemfire/main.adoc new file mode 100644 index 0000000..e18dc09 --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/http-gemfire/main.adoc @@ -0,0 +1,29 @@ +[[spring-cloud-data-flow-samples-gemfire-http-overview]] +:sectnums: +:docs_dir: ../../.. + +=== HTTP to Gemfire Demo + +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from an `http` endpoint and write to Gemfire using the `gemfire` sink. + +We will take you through the steps to configure and run Spring Cloud Data Flow server in either a https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started/[local] or https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#getting-started[Cloud Foundry] environment. + +NOTE: For legacy reasons the `gemfire` Spring Cloud Stream Apps are named after `Pivotal GemFire`. The code base for the commercial product has since been open sourced as `Apache Geode`. These samples should work with compatible versions of Pivotal GemFire or Apache Geode. Herein we will refer to the installed IMDG simply as `Geode`. + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* A Geode installation with a locator and cache server running +include::{docs_dir}/geode-setup.adoc[] + +include::local.adoc[] + +include::pcf.adoc[] + +==== Summary + +In this sample, you have learned: + +* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers +* How to use Spring Cloud Data Flow's `shell` +* How to create streaming data pipeline to connect and write to `gemfire` diff --git a/src/main/asciidoc/streaming/gemfire/http-gemfire/pcf.adoc b/src/main/asciidoc/streaming/gemfire/http-gemfire/pcf.adoc new file mode 100644 index 0000000..0799337 --- /dev/null +++ b/src/main/asciidoc/streaming/gemfire/http-gemfire/pcf.adoc @@ -0,0 +1,106 @@ +[[gemfire-http-cf]] +===== Using the Cloud Foundry Server +====== Additional Prerequisites + +* A Cloud Foundry instance + +* Running instance of a `rabbit` service in Cloud Foundry + +* Running instance of the https://docs.pivotal.io/p-cloud-cache/1-0/developer.html[Pivotal Cloud Cache for PCF] (PCC) service `cloudcache` in Cloud Foundry. + +* Cloud Data Flow Cloud Foundry Server +include::{docs_dir}/cloudfoundry-server.adoc[] + +====== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Get the PCC connection information ++ +``` +$ cf service-key cloudcache my-service-key +Getting key my-service-key for service instance cloudcache as ... + +{ + "locators": [ + "10.0.16.9[55221]", + "10.0.16.11[55221]", + "10.0.16.10[55221]" + ], + "urls": { + "gfsh": "http://...", + "pulse": "http://.../pulse" + }, + "users": [ + { + "password": , + "username": "cluster_operator" + }, + { + "password": , + "username": "developer" + } + ] +} +``` ++ +. Using `gfsh`, connect to the PCC instance as `cluster_operator` using the service key values and create the Stocks region. ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>create region --name Stocks --type=REPLICATE +``` ++ +. Create the stream, connecting to the PCC instance as developer ++ +This example creates an http endpoint to which we will post stock prices as a JSON document containing `symbol` and `price` fields. +The property `--json=true` to enable Geode's JSON support and configures the sink to convert JSON String payloads to https://geode.apache.org/releases/latest/javadoc/org/apache/geode/pdx/PdxInstance.html[PdxInstance], the recommended way +to store JSON documents in Geode. The `keyExpression` property is a SpEL expression used to extract the `symbol` value the PdxInstance to use as an entry key. ++ +NOTE: PDX serialization is very efficient and supports OQL queries without requiring a custom domain class. +Use of custom domain types requires these classes to be in the class path of both the stream apps and the cache server. +For this reason, the use of custom payload types is generally discouraged. ++ +``` +dataflow:>stream create --name stocks --definition "http --security.basic.enabled=false | gemfire --username=developer --password= --connect-type=locator --host-addresses=10.0.16.9:55221 --regionName=Stocks --keyExpression=payload.getField('symbol')" --deploy +``` + +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` + +. Post sample data pointing to the `http` endpoint ++ + +Get the url of the http source using `cf apps` ++ +``` +dataflow:>http post --target http:// --contentType application/json --data '{"symbol":"VMW","price":117.06}' +> POST (application/json) http://... {"symbol":"VMW","price":117.06} +> 202 ACCEPTED +``` ++ +. Using `gfsh`, connect to the PCC instance as `cluster_operator` using the service key values. ++ +``` +gfsh>connect --use-http --url= --user=cluster_operator --password= +gfsh>get --key='VMW' --region=/Stocks +Result : true +Key Class : java.lang.String +Key : VMW +Value Class : org.apache.geode.pdx.internal.PdxInstanceImpl + +symbol | price +------ | ------ +VMW | 117.06 +``` ++ +. You're done! diff --git a/src/main/asciidoc/streaming/jdbc/http-mysql/local.adoc b/src/main/asciidoc/streaming/jdbc/http-mysql/local.adoc new file mode 100644 index 0000000..b0f1dea --- /dev/null +++ b/src/main/asciidoc/streaming/jdbc/http-mysql/local.adoc @@ -0,0 +1,74 @@ +==== Using the Local Server + +===== Additional Prerequisites + +* A running local Data Flow Server +include::{docs_dir}/local-server.adoc[] + +* Running instance of link:http://kafka.apache.org/downloads.html[Kafka] +* Running instance of link:http://www.mysql.com/[MySQL] +* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] or link:https://www.dbvis.com/[DbVisualizer] +* Create the `test` database with a `names` table (in MySQL) using: ++ +``` +CREATE DATABASE test; +USE test; +CREATE TABLE names +( + name varchar(255) +); +``` + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Kafka binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven +``` ++ +. Create the stream ++ +``` +dataflow:>stream create --name mysqlstream --definition "http --server.port=8787 | jdbc --tableName=names --columns=name --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver --spring.datasource.url='jdbc:mysql://localhost:3306/test'" --deploy + +Created and deployed new stream 'mysqlstream' +``` +NOTE: If MySQL isn't running on default port on `localhost` or if you need username and password to connect, use one of the following options to specify the necessary connection parameters: `--spring.datasource.url='jdbc:mysql://:/' --spring.datasource.username= --spring.datasource.password=` + ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Notice that `mysqlstream-http` and `mysqlstream-jdbc` https://github.com/spring-cloud-stream-app-starters//[Spring Cloud Stream] applications are running as Spring Boot applications within the Local `server` as collocated processes. ++ + +[source,console,options=nowrap] +---- +2016-05-03 09:29:55.918 INFO 65162 --- [nio-9393-exec-3] o.s.c.d.spi.local.LocalAppDeployer : deploying app mysqlstream.jdbc instance 0 + Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-dataflow-6850863945840320040/mysqlstream1-1462292995903/mysqlstream.jdbc +2016-05-03 09:29:55.939 INFO 65162 --- [nio-9393-exec-3] o.s.c.d.spi.local.LocalAppDeployer : deploying app mysqlstream.http instance 0 + Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-dataflow-6850863945840320040/mysqlstream-1462292995934/mysqlstream.http +---- + +. Post sample data pointing to the `http` endpoint: `http://localhost:8787` [`8787` is the `server.port` we specified for the `http` source in this case] + ++ +``` +dataflow:>http post --contentType 'application/json' --target http://localhost:8787 --data "{\"name\": \"Foo\"}" +> POST (application/json;charset=UTF-8) http://localhost:8787 {"name": "Spring Boot"} +> 202 ACCEPTED +``` ++ +. Connect to the MySQL instance and query the table `test.names` to list the new rows: ++ +``` +select * from test.names; +``` ++ +. You're done! diff --git a/src/main/asciidoc/streaming/jdbc/http-mysql/main.adoc b/src/main/asciidoc/streaming/jdbc/http-mysql/main.adoc new file mode 100644 index 0000000..bd8ce3b --- /dev/null +++ b/src/main/asciidoc/streaming/jdbc/http-mysql/main.adoc @@ -0,0 +1,25 @@ +:sectnums: +:docs_dir: ../../.. + +=== HTTP to MySQL Demo + +In this demonstration, you will learn how to build a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from an `http` endpoint and write to MySQL database using `jdbc` sink. + +We will take you through the steps to configure and Spring Cloud Data Flow server in either a https://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#getting-started/[local] or https://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current/reference/htmlsingle/#getting-started[Cloud Foundry] environment. + +==== Prerequisites +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] + +include::local.adoc[] + +include::pcf.adoc[] + +==== Summary + +In this sample, you have learned: + +* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers +* How to use Spring Cloud Data Flow's `shell` +* How to create streaming data pipeline to connect and write to `MySQL` +* How to scale applications on `Pivotal Cloud Foundry` diff --git a/src/main/asciidoc/streaming/jdbc/http-mysql/pcf.adoc b/src/main/asciidoc/streaming/jdbc/http-mysql/pcf.adoc new file mode 100644 index 0000000..bdec14d --- /dev/null +++ b/src/main/asciidoc/streaming/jdbc/http-mysql/pcf.adoc @@ -0,0 +1,104 @@ + +==== Using the Cloud Foundry Server + +===== Additional Prerequisites + +* Cloud Foundry instance + +* Running instance of `rabbit` in Cloud Foundry +* Running instance of `mysql` in Cloud Foundry +* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] or link:https://www.dbvis.com/[DbVisualizer] +* Create the `names` table (in MySQL) using: ++ +``` +CREATE TABLE names +( + name varchar(255) +); +``` ++ +* The Spring Cloud Data Flow Cloud Foundry Server +include::{docs_dir}/cloudfoundry-server.adoc[] + +===== Building and Running the Demo + +. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] the out-of-the-box applications for the Rabbit binder ++ +include::{docs_dir}/maven-access.adoc[] ++ +``` +dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven +``` ++ +. Create the stream ++ + +``` +dataflow:>stream create --name mysqlstream --definition "http | jdbc --tableName=names --columns=name" +Created new stream 'mysqlstream' + +dataflow:>stream deploy --name mysqlstream --properties "app.jdbc.spring.cloud.deployer.cloudfoundry.services=mysql" +Deployed stream 'mysqlstream' + +``` ++ + +NOTE: By supplying the `app.jdbc.spring.cloud.deployer.cloudfoundry.services=mysql` property, we are deploying the stream with `jdbc-sink` to automatically bind to `mysql` service and only this application in the stream gets the service binding. This also eliminates the requirement to supply `datasource` credentials in stream definition. ++ +. Verify the stream is successfully deployed ++ +``` +dataflow:>stream list +``` ++ +. Notice that `mysqlstream-http` and `mysqlstream-jdbc` https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as _cloud-native_ (microservice) applications in Cloud Foundry ++ + +``` +$ cf apps +Getting apps in org user-dataflow / space development as user... +OK + +name requested state instances memory disk urls +mysqlstream-http started 1/1 1G 1G mysqlstream-http.app.io +mysqlstream-jdbc started 1/1 1G 1G mysqlstream-jdbc.app.io +dataflow-server started 1/1 1G 1G dataflow-server.app.io +``` ++ +. Lookup the `url` for `mysqlstream-http` application from the list above. Post sample data pointing to the `http` endpoint: `` ++ +``` +http post --contentType 'application/json' --target http://mysqlstream-http.app.io --data "{\"name\": \"Bar"}" +> POST (application/json;charset=UTF-8) http://mysqlstream-http.app.io {"name": "Bar"} +> 202 ACCEPTED +``` ++ +. Connect to the MySQL instance and query the table `names` to list the new rows: ++ +``` +select * from names; +``` + ++ +. Now, let's take advantage of Pivotal Cloud Foundry's platform capability. Let's scale the `mysqlstream-http` application from 1 to 3 instances ++ +``` +$ cf scale mysqlstream-http -i 3 +Scaling app mysqlstream-http in org user-dataflow / space development as user... +OK +``` ++ +. Verify App instances (3/3) running successfully ++ +``` +$ cf apps +Getting apps in org user-dataflow / space development as user... +OK + +name requested state instances memory disk urls +mysqlstream-http started 3/3 1G 1G mysqlstream-http.app.io +mysqlstream-jdbc started 1/1 1G 1G mysqlstream-jdbc.app.io +dataflow-server started 1/1 1G 1G dataflow-server.app.io +``` ++ +. You're done! diff --git a/tasks/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar b/src/main/asciidoc/tasks/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar similarity index 100% rename from tasks/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar rename to src/main/asciidoc/tasks/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar diff --git a/tasks/simple-batch-job/README.adoc b/src/main/asciidoc/tasks/simple-batch-job/main.adoc similarity index 72% rename from tasks/simple-batch-job/README.adoc rename to src/main/asciidoc/tasks/simple-batch-job/main.adoc index 662243b..d912aa5 100644 --- a/tasks/simple-batch-job/README.adoc +++ b/src/main/asciidoc/tasks/simple-batch-job/main.adoc @@ -1,39 +1,23 @@ :sectnums: -= Batch Job on Cloud Foundry +:docs_dir: ../.. +=== Batch Job on Cloud Foundry In this demonstration, you will learn how to orchestrate short-lived data processing application (_eg: Spring Batch Jobs_) using http://cloud.spring.io/spring-cloud-task/[Spring Cloud Task] and http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] on Cloud Foundry. -== Using Cloud Foundry Server +==== Prerequisites -=== Prerequisites - -In order to get started, make sure that you have the following components: - -* Local https://pivotal.io/pcf-dev[PCFDev] instance +* Local https://pivotal.io/pcf-dev[PCFDev] instance * Local install of https://github.com/cloudfoundry/cli[cf CLI] command line tool -* Local build of https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Local build of Spring Cloud Data Flow's https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[Cloud Foundry Server] * Running instance of mysql in PCFDev +* A Running Data Flow Shell +include::{docs_dir}/shell.adoc[] +* The Spring Cloud Data Flow Cloud Foundry Server running in PCFDev +include::{docs_dir}/cloudfoundry-server.adoc[] + +==== Building and Running the Demo NOTE: PCF 1.7.12 or greater is required to run Tasks on Spring Cloud Data Flow. As of this writing, PCFDev and PWS supports builds upon this version. -=== Running the Sample in Cloud Foundry - -. Verify that CF instance is reachable -+ - -``` -→ cf api -api endpoint: https://api.local.pcfdev.io -api version: 2.75.0 - -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -No apps found -``` -+ . Task support needs to be enabled on pcf-dev. Being logged as `admin`, issue the following command: + ``` @@ -44,32 +28,14 @@ OK Feature task_creation Enabled. ``` -+ -. Follow the http://docs.spring.io/spring-cloud-dataflow-server-cloudfoundry/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started[getting-started] instructions to deploy Spring Cloud Data Flow's Cloud Foundry Server - + NOTE: For this sample, all you need is the `mysql` service and in PCFDev, the `mysql` service comes with a different plan. From CF CLI, create the service by: `cf create-service p-mysql 512mb mysql` and bind this service to `dataflow-server` by: `cf bind-service dataflow-server mysql`. + NOTE: All the apps deployed to PCFDev start with low memory by default. It is recommended to change it to at least 768MB for `dataflow-server`. Ditto for every app spawned *by* Spring Cloud Data Flow. Change the memory by: `cf set-env dataflow-server SPRING_CLOUD_DEPLOYER_CLOUDFOUNDRY_MEMORY 512`. Likewise, we would have to skip SSL validation by: `cf set-env dataflow-server SPRING_CLOUD_DEPLOYER_CLOUDFOUNDRY_SKIP_SSL_VALIDATION true`. -. Once you complete the instructions, you'll be able to list the newly deployed `dataflow-server` -+ - -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -dataflow-server started 1/1 512M 512M dataflow-server.local.pcfdev.io -``` -+ - -NOTE: The `ORG`, `SPACE` and `USER` could vary depending on your Cloud Foundry environment in use. - -. Tasks in Spring Cloud Data Flow require an RDBMS to host "task repository" (see http://docs.spring.io/spring-cloud-dataflow/docs/current-SNAPSHOT/reference/htmlsingle/#spring-cloud-dataflow-task-repository[here] for more details), so let's instruct the Spring Cloud Data Flow server to bind the `mysql` service to each deployed task: +. Tasks in Spring Cloud Data Flow require an RDBMS to host "task repository" (see http://docs.spring.io/spring-cloud-dataflow/docs/current/reference/htmlsingle/#spring-cloud-dataflow-task-repository[here] for more details), so let's instruct the Spring Cloud Data Flow server to bind the `mysql` service to each deployed task: + @@ -106,43 +72,10 @@ No staging env variables have been set . Notice that `dataflow-server` application is started and ready for interaction via `http://dataflow-server.local.pcfdev.io` endpoint -. Connect to Spring Cloud Data Flow's `shell`. + - -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -server-unknown:> -``` -+ -. Connect `shell` with the `server` running at `http://dataflow-server.local.pcfdev.io` -+ - -``` -server-unknown:>dataflow config server http://dataflow-server.local.pcfdev.io -Successfully targeted http://dataflow-server.local.pcfdev.io -``` -+ - -. Let's build and register the batch-job https://github.com/spring-cloud/spring-cloud-task/tree/master/spring-cloud-task-samples/batch-job[example] from Spring Cloud Task samples. For convenience, the final https://github.com/spring-cloud/spring-cloud-dataflow-samples/raw/master/tasks/simple-batch-job/batch-job-1.0.0.BUILD-SNAPSHOT.jar[uber-jar artifact] is provided with this sample +. Build and register the batch-job https://github.com/spring-cloud/spring-cloud-task/tree/master/spring-cloud-task-samples/batch-job[example] from Spring Cloud Task samples. For convenience, the final https://github.com/spring-cloud/spring-cloud-dataflow-samples/raw/master/src/main/asciidoc/tasks/simple-batch-job/batch-job-1.0.0.BUILD-SNAPSHOT.jar[uber-jar artifact] is provided with this sample. + - ``` dataflow:>app register --type task --name simple_batch_job --uri https://github.com/spring-cloud/spring-cloud-dataflow-samples/raw/master/tasks/simple-batch-job/batch-job-1.3.0.BUILD-SNAPSHOT.jar ``` @@ -154,7 +87,7 @@ dataflow:>app register --type task --name simple_batch_job --uri https://github. ``` dataflow:>task create foo --definition "simple_batch_job" ``` -NOTE: Unlike Streams, the Task definitions don't require explicit deployment. They can be launched on-demand, scheduled, or triggered by streams. +NOTE: Unlike Streams, the Task definitions don't require explicit deployment. They can be launched on-demand, scheduled, or triggered by streams. + @@ -162,7 +95,7 @@ NOTE: Unlike Streams, the Task definitions don't require explicit deployment. Th + ``` -cf apps +$ cf apps Getting apps in org pcfdev-org / space pcfdev-space as user... OK @@ -176,7 +109,7 @@ dataflow-server started 1/1 768M 512M dataflow-server. + ``` -dataflow:>task launch foo +dataflow:>task launch foo ``` + @@ -184,8 +117,9 @@ dataflow:>task launch foo + -``` -→ cf logs foo +[source,console,options=nowrap] +---- +$ cf logs foo Retrieving logs for app foo in org pcfdev-org / space pcfdev-space as user... 2016-08-14T18:48:54.22-0700 [APP/TASK/foo/0]OUT Creating container @@ -214,12 +148,13 @@ Retrieving logs for app foo in org pcfdev-org / space pcfdev-space as user... 2016-08-14T18:49:07.71-0700 [APP/TASK/foo/0]OUT Exit status 0 2016-08-14T18:49:07.78-0700 [APP/TASK/foo/0]OUT Destroying container 2016-08-14T18:49:08.47-0700 [APP/TASK/foo/0]OUT Successfully destroyed container - -``` -NOTE: Verify `job1` and `job2` operations embeddded in `simple-batch-job` application are launched independently and they returned with the status `COMPLETED`. +---- ++ +NOTE: Verify `job1` and `job2` operations embeddded in `simple-batch-job` application are launched independently and they returned with the status `COMPLETED`. + ++ NOTE: Unlike LRPs in Cloud Foundry, tasks are short-lived, so the logs aren't always available. They are generated only when the Task application runs; at the end of Task operation, the container that ran the Task application is destroyed to free-up resources. + @@ -228,7 +163,7 @@ NOTE: Unlike LRPs in Cloud Foundry, tasks are short-lived, so the logs aren't al + ``` -→ cf apps +$ cf apps Getting apps in org pcfdev-org / space pcfdev-space as user... OK @@ -242,20 +177,22 @@ foo stopped 0/1 1G 1G + -``` +[source,console,options=nowrap] +---- dataflow:>task execution list ╔══════════════════════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗ ║ Task Name │ID│ Start Time │ End Time │Exit Code║ ╠══════════════════════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣ ║foo │1 │Sun Aug 14 18:49:05 PDT 2016│Sun Aug 14 18:49:07 PDT 2016│0 ║ ╚══════════════════════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝ -``` +---- . Verify Job execution details + -``` +[source,console,options=nowrap] +---- dataflow:>job execution list ╔═══╤═══════╤═════════╤════════════════════════════╤═════════════════════╤══════════════════╗ ║ID │Task ID│Job Name │ Start Time │Step Execution Count │Definition Status ║ @@ -263,14 +200,14 @@ dataflow:>job execution list ║2 │1 │job2 │Sun Aug 14 18:49:07 PDT 2016│1 │Destroyed ║ ║1 │1 │job1 │Sun Aug 14 18:49:06 PDT 2016│1 │Destroyed ║ ╚═══╧═══════╧═════════╧════════════════════════════╧═════════════════════╧══════════════════╝ -``` +---- + -== Summary +==== Summary In this sample, you have learned: * How to register and orchestrate Spring Batch jobs in Spring Cloud Data Flow * How to use the `cf` CLI in the context of Task applications orchestrated by Spring Cloud Data Flow -* How to verify task executions and task repository +* How to verify task executions and task repository diff --git a/src/main/docbook/css/highlight.css b/src/main/docbook/css/highlight.css new file mode 100644 index 0000000..ffefef7 --- /dev/null +++ b/src/main/docbook/css/highlight.css @@ -0,0 +1,35 @@ +/* + code highlight CSS resemblign the Eclipse IDE default color schema + @author Costin Leau +*/ + +.hl-keyword { + color: #7F0055; + font-weight: bold; +} + +.hl-comment { + color: #3F5F5F; + font-style: italic; +} + +.hl-multiline-comment { + color: #3F5FBF; + font-style: italic; +} + +.hl-tag { + color: #3F7F7F; +} + +.hl-attribute { + color: #7F007F; +} + +.hl-value { + color: #2A00FF; +} + +.hl-string { + color: #2A00FF; +} \ No newline at end of file diff --git a/src/main/docbook/css/manual-multipage.css b/src/main/docbook/css/manual-multipage.css new file mode 100644 index 0000000..0c48453 --- /dev/null +++ b/src/main/docbook/css/manual-multipage.css @@ -0,0 +1,9 @@ +@IMPORT url("manual.css"); + +body.firstpage { + background: url("../images/background.png") no-repeat center top; +} + +div.part h1 { + border-top: none; +} diff --git a/src/main/docbook/css/manual-singlepage.css b/src/main/docbook/css/manual-singlepage.css new file mode 100644 index 0000000..4a7fd14 --- /dev/null +++ b/src/main/docbook/css/manual-singlepage.css @@ -0,0 +1,6 @@ +@IMPORT url("manual.css"); + +body { + background: url("../images/background.png") no-repeat center top; +} + diff --git a/src/main/docbook/css/manual.css b/src/main/docbook/css/manual.css new file mode 100644 index 0000000..2500583 --- /dev/null +++ b/src/main/docbook/css/manual.css @@ -0,0 +1,348 @@ +@IMPORT url("highlight.css"); + +html { + padding: 0pt; + margin: 0pt; +} + +body { + color: #333333; + margin: 15px 30px; + font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +code { + font-size: 16px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +:not(a)>code { + color: #6D180B; +} + +:not(pre)>code { + background-color: #F2F2F2; + border: 1px solid #CCCCCC; + border-radius: 4px; + padding: 1px 3px 0; + text-shadow: none; + white-space: nowrap; +} + +body>*:first-child { + margin-top: 0 !important; +} + +div { + margin: 0pt; +} + +hr { + border: 1px solid #CCCCCC; + background: #CCCCCC; +} + +h1,h2,h3,h4,h5,h6 { + color: #000000; + cursor: text; + font-weight: bold; + margin: 30px 0 10px; + padding: 0; +} + +h1,h2,h3 { + margin: 40px 0 10px; +} + +h1 { + margin: 70px 0 30px; + padding-top: 20px; +} + +div.part h1 { + border-top: 1px dotted #CCCCCC; +} + +h1,h1 code { + font-size: 32px; +} + +h2,h2 code { + font-size: 24px; +} + +h3,h3 code { + font-size: 20px; +} + +h4,h1 code,h5,h5 code,h6,h6 code { + font-size: 18px; +} + +div.book,div.chapter,div.appendix,div.part,div.preface { + min-width: 300px; + max-width: 1200px; + margin: 0 auto; +} + +p.releaseinfo { + font-weight: bold; + margin-bottom: 40px; + margin-top: 40px; +} + +div.authorgroup { + line-height: 1; +} + +p.copyright { + line-height: 1; + margin-bottom: -5px; +} + +.legalnotice p { + font-style: italic; + font-size: 14px; + line-height: 1; +} + +div.titlepage+p,div.titlepage+p { + margin-top: 0; +} + +pre { + line-height: 1.0; + color: black; +} + +a { + color: #4183C4; + text-decoration: none; +} + +p { + margin: 15px 0; + text-align: left; +} + +ul,ol { + padding-left: 30px; +} + +li p { + margin: 0; +} + +div.table { + margin: 1em; + padding: 0.5em; + text-align: center; +} + +div.table table,div.informaltable table { + display: table; + width: 100%; +} + +div.table td { + padding-left: 7px; + padding-right: 7px; +} + +.sidebar { + line-height: 1.4; + padding: 0 20px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; +} + +.sidebar p.title { + color: #6D180B; +} + +pre.programlisting,pre.screen { + font-size: 15px; + padding: 6px 10px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; + clear: both; + overflow: auto; + line-height: 1.4; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +table { + border-collapse: collapse; + border-spacing: 0; + border: 1px solid #DDDDDD !important; + border-radius: 4px !important; + border-collapse: separate !important; + line-height: 1.6; +} + +table thead { + background: #F5F5F5; +} + +table tr { + border: none; + border-bottom: none; +} + +table th { + font-weight: bold; +} + +table th,table td { + border: none !important; + padding: 6px 13px; +} + +table tr:nth-child(2n) { + background-color: #F8F8F8; +} + +td p { + margin: 0 0 15px 0; +} + +div.table-contents td p { + margin: 0; +} + +div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist * + { + border: none !important; + background: none !important; + margin: 0; +} + +div.important p,div.note p,div.tip p,div.warning p { + color: #6F6F6F; + line-height: 1.6; +} + +div.important code,div.note code,div.tip code,div.warning code { + background-color: #F2F2F2 !important; + border: 1px solid #CCCCCC !important; + border-radius: 4px !important; + padding: 1px 3px 0 !important; + text-shadow: none !important; + white-space: nowrap !important; +} + +.note th,.tip th,.warning th { + display: none; +} + +.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td + { + border-right: 1px solid #CCCCCC !important; + padding-top: 10px; +} + +div.calloutlist p,div.calloutlist td { + padding: 0; + margin: 0; +} + +div.calloutlist>table>tbody>tr>td:first-child { + padding-left: 10px; + width: 30px !important; +} + +div.important,div.note,div.tip,div.warning { + margin-left: 0px !important; + margin-right: 20px !important; + margin-top: 20px; + margin-bottom: 20px; + padding-top: 10px; + padding-bottom: 10px; +} + +div.toc { + line-height: 1.2; +} + +dl,dt { + margin-top: 1px; + margin-bottom: 0; +} + +div.toc>dl>dt { + font-size: 32px; + font-weight: bold; + margin: 30px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dt { + font-size: 24px; + font-weight: bold; + margin: 20px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dd>dl>dt { + font-weight: bold; + font-size: 20px; + margin: 10px 0 0 0; +} + +tbody.footnotes * { + border: none !important; +} + +div.footnote p { + margin: 0; + line-height: 1; +} + +div.footnote p sup { + margin-right: 6px; + vertical-align: middle; +} + +div.navheader { + border-bottom: 1px solid #CCCCCC; +} + +div.navfooter { + border-top: 1px solid #CCCCCC; +} + +.title { + margin-left: -1em; + padding-left: 1em; +} + +.title>a { + position: absolute; + visibility: hidden; + display: block; + font-size: 0.85em; + margin-top: 0.05em; + margin-left: -1em; + vertical-align: text-top; + color: black; +} + +.title>a:before { + content: "\00A7"; +} + +.title:hover>a,.title>a:hover,.title:hover>a:hover { + visibility: visible; +} + +.title:focus>a,.title>a:focus,.title:focus>a:focus { + outline: 0; +} + +.mediaobject img { + max-width: 100%; +} diff --git a/src/main/docbook/images/background.png b/src/main/docbook/images/background.png new file mode 100644 index 0000000000000000000000000000000000000000..d4195e5b32cd5f878652c5195bd674a5a6304855 GIT binary patch literal 10947 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 literal 0 HcmV?d00001 diff --git a/src/main/docbook/images/caution.png b/src/main/docbook/images/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..8a5e4fca039d0247dcf55ae0e719cdb457509422 GIT binary patch literal 2099 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

)_adS|n?p|6d5ZKl`PzD7od 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 literal 0 HcmV?d00001 diff --git a/src/main/docbook/images/logo.png b/src/main/docbook/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bb1f4f9fa3cfb9665bfbe00db0f622a5a13faff6 GIT binary patch literal 19499 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 literal 0 HcmV?d00001 diff --git a/src/main/docbook/images/logo.svg b/src/main/docbook/images/logo.svg new file mode 100644 index 0000000..e4624f7 --- /dev/null +++ b/src/main/docbook/images/logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/docbook/images/note.png b/src/main/docbook/images/note.png new file mode 100644 index 0000000000000000000000000000000000000000..88d997b17cfe703280d3a33e3f7c285a4ce6c8a6 GIT binary patch literal 2257 zcmbVOc~}!?8jt0%wJO?rR6vCx90KN;$uT)dKypElKnRgUJaCwd5Fm%i5JI?F5NZ{L zHB!K;6~%M$V1?>pq28#7tClK{yXb1Wwu?(E7V(JeM8)nOZvWVMX6F08ci!Lcy`N`3 zRmMkqPWG8hB9T1hF%lKAdbyuT9>n{*eLWY6#T%Du@g&n~JQuNGq$r&!4Flu`Bpp*> zh%RqUHzpvFJTmlZEv{9>@llh3hPZWTc7vHflSqO{yBR^VFdRt3()C6mdFU^lWI(SI zk~M4vs4$DM41J8lf+acP)u|5Q7d9H%x_Cd^XHyaDX=#nXqQj zt>&vFvNyJflaQQ&<7Pgco|~IX%Vp9`mUKGA-Zp( zOJtG50yzv2=0Xrx46(Qj83@V53@*$QjdQ#U%j3e3l*8gOAt(xhqztY^3`s$@h$SN! zBqG*0R&KQ7h!Mrc?dl1;Z?K%-#qz}#48ctnwaJt{-T}%C6K=9*n9P7U2?jzG2&y-_ z1)=T&y^dFcS@bqcC$pFgz^e@N_3!Y2&4rmVrc?^b{#WF$vAX{!YjnaHy1PC8t6j!L zL=U>RZ=0Vuyd59RNX(3d7!LK(`xl6rBPrw5(!bs96XC4+vN`n!pkNhnvKs;x&pmV! z^p5t4F5vmbc<*Tg!?VGlB>@XnzNdTWfhvE25$e1Mo;VNrFPPX7U z(3k?AET0>c;EQjdF;|7qmM;id8Z2DH;$?xdi*jLQS;UTmTiQ;84~KpVQTS}!1G7>???1T1M8Y2Y^v{gyWH4>vrEALt zW@fUDlD9Q{=doHaIiz}LsVtu#Tf|>gNSPn)uUj7xxbS*QsNLaH+;@qq1yM5)eX8Xer{FRzM~ z7xK|ff|w#cs13!6!+4oAeiqo&#|^o&-HT^JJ+1KLT73G&i2y$6Z`@c^KzV`9OsHC8!WcLRbRl_HObYx+233S$HvBP zx5xC8NE3$Tk|?#kKW%jS#1E2l4~Dm9y?iNEMtGE`{31iwDR0{;frQ`P~3kjC$lu_eqZs}wAR(baf^>n-dr`hd)oUmm$gnF zbD^_eYPM#zynGxf-a!tS6u8|n_+WHspz~^faii1kX{e03c}{&}W2fu+^!IEjlU-

MvJZJ$)LTqJA+@mbLxmkyPc#tU=W5xPJ%q2sZXv`v(Ui?>!8Tjh_mSOc$O+ zW<-$ZjJfV@LAsB%Biz5w(;fXV?CW1TB9(ujH2(XqZD*&_2O2L-EZJ~mTUSoq*g)q^ zQ!j3qa>DzQ*dH!xN(0O3n$-7HmkYk_eQXG-gI*K|{dncP!DXswNa?P_Z}nzo#*v#J zQ5S9ROsaZ%ZqC6y?VF!Q1^;o|wu*kH=E=`8B``9)uFtN|s?>Xw*7?*`wfqP}<_A~q zd8VVPq*k-7ZPhbSEogsT%F|x0xuT7xdRv7>Rev?4wv{qrDN}+xS$8V5!!ga&#Y1*BgqL?&c}jPc zG_JlfMSD5I%DQQcHXTbGWQtKpeL6yAB|UI5CQ=~#`}=c}Um;E%R)9u^qI0>&GHQ-g zOm;DCkym+{WF$}@UWrV1mtnTPtu!WtY$r7BOpo|N_#mqWGhK#KR0MD7eW*yPaY&xBTRfcG-E5p&`2dq z875XFdy+3GStd(wD_Mg`dys8Xd_houJju_&*4)mZt2Tk1H)DTRJY^_lf>>*ZU2Th5 zWQ3Ly{;kf91GM2s4Vfv8a-fcsXpb+4t> zmM%11X*>M&PQZNVdARf4d*2x!aq1>jOzQ?>>R)(Ok;sOJ)7jfk$Fdif23? z-}3V78&9qod*O;uGk%fEW^;|k`Lo>bOq2iF72o-IGb2gTw+4B~#iYz(oL}sS7|$R2 zDGfrR{|@~AQJ&v(#4u|ZtJP}t520N48P!$8U;|Vfuq=8>E$w`o2Jf`%eqhqbr%IH1zV?O3uDWqKZId-wMQ*MFefpD5X*w@ zok{kNA?%%$F{M!OUcE^^x{~(wkHK|_*9Yg`KNS88FaVH_sda1Xfs6nE002ovPDHLk FV1jwin)(0$ literal 0 HcmV?d00001 diff --git a/src/main/docbook/images/warning.png b/src/main/docbook/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..0d5b5244605adbb7ab05a1549746a9c35490f95b GIT binary patch literal 2130 zcmbVNYg7|w8V(4q($)50y>JmGlLW#g$xLn}Vd2Si)}#|ptPAQp3Bp-3!-lL0;i^LY?;i#f0m5s49g z3h?3rDQg~EDPlm?FKkgKIcWEK-3X6YU0uzs7H|nq84s39r2!5;pF?SI$QqXy^Ko1x zV~zpENvp@<_Bsd`5MabC#3rvCq&$5dg43yGR zAdy0-rWjC#a1N_+kzUMY#pmogD7!DP(9dEKr3c5ngvUq_6>}Y+w-a81v=eSXnIi_+ zI?U>D1q2C!0zHox#XXKH+@|&rPT*OF5yvY$5J|)WwLqnU)c-5;=UChSlQkaY3@^|g z|J5#YBB}=i+n3Ex9bS$P?xJSKLk)-HHII@;3qG#TG^!+aj>0QkO~7kB0+|yM;YrGB zF>Ge@isQ#73%Tp#k_(tInh3U$uJWY-+DND*o}L-CB5g@#9YWWw~pxZ!Obm>yN#ZHFvL0zA3vNCTJ=t?)~`2O1M{L6un=ml<2x zQEYfifmA?Pz0tqRs^2Utt1pU0BQB1eIY0U_I}c1Y#PP7Ci5s7#IJn}xK{G+{_v^Z+1V#$Erodv>d}ew>RP0wzw+GWkGCBlS1Oj5Z!5NK zUuSR6>pa}RSEZ;qE_w1l#`hQX4E67U6NeP zHZ`T&wj0_H)t|Y1thUqnhub?%e)Y07;a^Tq%FO&iQkR&`qG!dh*2WfW(HuRQj*_DI zeCD1bUA|tMwjOb8E|FRIn$pzEU!2j_N}1Z2ig)vbr5xA0rjC70cmI6*%Uf->hWzaZ z{33HABO5q)vRhzDly2l691@+q3O{}NbSzx+I*k@|L4&3leK#$>u+T#TvTELfKb|IH zc23atf3vmfCa0&TWY@iuoA_Pm<0~ttEC*ut`isb^jXS>X^Sp=l?RXN_OJ*&usGXg$ zTlTv;Ch^vhLDf&+62jl64*&D+=+`sN_dap_1W%p|KQVYIdgPL5uRE9(c4On)DXndL zLNq?%!-u*zmMxyYc4m4Nr>>=A=s}PkJkqr&E^b9>5g+}c1%X}3|WKcg&spcJQ)05zI<<5LTBhNKRg$XRTi2{j)yl_ zj4~kKOvr+m(;vw~9zVh(zC-y9jqQnguz5r7FRq^MyKuXAENp(TAzUVtg&Ts+B_s7) zGn+fN0sG>9GjsPLKTRrvCd`71IZulJ1_1jO9KWbD&_@2UC+LTNpxxrdz#E|j|2nA9 zzB!UTyfAEJ&#%$pQ>QX#8vk@_a5iqukMF;8`wRKe{BI}5$H%OROs4J1#j)|?p|YSh z_SpR^e`VE#F52;WL{!+L(yZLRh40*KS;@box;9(-tE)`mcVp27O*>Z{_Lb*5T3cJA yr~0nPHtg2+UHi&&$8ha;`+hiaUmw&!n@8(?5PqF(KE5>Ym)EG)p&uyBP5%a8^# + + + + + + + 1 + 0 + 1 + + + + images/ + .png + + + book toc,title + 3 + + + + + diff --git a/src/main/docbook/xsl/epub.xsl b/src/main/docbook/xsl/epub.xsl new file mode 100644 index 0000000..031406c --- /dev/null +++ b/src/main/docbook/xsl/epub.xsl @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/src/main/docbook/xsl/html-multipage.xsl b/src/main/docbook/xsl/html-multipage.xsl new file mode 100644 index 0000000..be9cc52 --- /dev/null +++ b/src/main/docbook/xsl/html-multipage.xsl @@ -0,0 +1,73 @@ + + + + + + + + + + css/manual-multipage.css + + '5' + '1' + + + + + + + + + + + + + + + + + + + + firstpage + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/docbook/xsl/html-singlepage.xsl b/src/main/docbook/xsl/html-singlepage.xsl new file mode 100644 index 0000000..6bd4ac8 --- /dev/null +++ b/src/main/docbook/xsl/html-singlepage.xsl @@ -0,0 +1,30 @@ + + + + + + + + + + css/manual-singlepage.css + + diff --git a/src/main/docbook/xsl/html.xsl b/src/main/docbook/xsl/html.xsl new file mode 100644 index 0000000..fd96f9a --- /dev/null +++ b/src/main/docbook/xsl/html.xsl @@ -0,0 +1,141 @@ + + + + + + + + + + + 1 + + + 1 + + + + 120 + images/callouts/ + .png + + + text/css + + text-align: left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + + +

+

Authors

+ +
+ + + + + + + + + + + + + + + + + + # + + + + + + + diff --git a/src/main/docbook/xsl/pdf.xsl b/src/main/docbook/xsl/pdf.xsl new file mode 100644 index 0000000..3074094 --- /dev/null +++ b/src/main/docbook/xsl/pdf.xsl @@ -0,0 +1,591 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + auto + + + + + underline + #204060 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + + + + + + + + Copyright © + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -5em + -5em + 8pt + + + + + + + + + + + + + + + please define title in your docbook file! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8pt + + + + + + + + + + + + + + + + + + + + + + + + + please define title in your docbook file! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + false + + + Helvetica + 10 + 8 + Helvetica + + + 1.4 + + + + left + bold + + + pt + + + + + + + + + + + + + + + 0.6em + 0.6em + 0.6em + + + pt + + 0.1em + 0.1em + 0.1em + + + + 0.4em + 0.4em + 0.4em + + + pt + + 0.1em + 0.1em + 0.1em + + + + 0.4em + 0.4em + 0.4em + + + pt + + 0.1em + 0.1em + 0.1em + + + + 0.3em + 0.3em + 0.3em + + + pt + + 0.1em + 0.1em + 0.1em + + + + + + + + 4pt + 4pt + 4pt + 4pt + + + + 0.1pt + 0.1pt + + + + + + + + + + + + + + + + 7pt + wrap + 1 + + + + 1em + 1em + 1em + 0.1em + 0.1em + 0.1em + + #444444 + solid + 0.1pt + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + 0.5em + + + + 1 + + #F0F0F0 + + + + 0.1em + 0.1em + 0.1em + 0.1em + 0.1em + 0.1em + + + + 0.5em + 0.5em + 0.5em + 0.1em + 0.1em + 0.1em + + + + #444444 + solid + 0.1pt + #F0F0F0 + + + + + + + normal + italic + + + pt + + false + 0.1em + 0.1em + 0.1em + + + + + + 0 + 1 + + + 90 + + + + + + figure after + example after + equation before + table before + procedure before + + + + 1 + 0pt + + + + + + + + + + + + + + + + + + + + 18pt + + + + 0.1em + 2em + .75pt + solid + #5c5c4f + 0.5em + 1.5em + 1.5em + 1.5em + 1.5em + 1.5em + 1.5em + + + + 10pt + bold + false + always + 0 + + + + 0em + 0em + 0em + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/docbook/xsl/xslthl-config.xml b/src/main/docbook/xsl/xslthl-config.xml new file mode 100644 index 0000000..e4d677f --- /dev/null +++ b/src/main/docbook/xsl/xslthl-config.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/docbook/xsl/xslthl/asciidoc-hl.xml b/src/main/docbook/xsl/xslthl/asciidoc-hl.xml new file mode 100644 index 0000000..5478b1d --- /dev/null +++ b/src/main/docbook/xsl/xslthl/asciidoc-hl.xml @@ -0,0 +1,41 @@ + + + + + //// + //// + + + // + + + + ^(={1,6} .+)$ + + MULTILINE + + + ^(\.[^\.\s].+)$ + + MULTILINE + + + ^(:!?\w.*?:) + + MULTILINE + + + ^(-|\*{1,5}|\d*\.{1,5})(?= .+$) + + MULTILINE + + + ^(\[.+\])$ + + MULTILINE + + diff --git a/src/main/docbook/xsl/xslthl/bourne-hl.xml b/src/main/docbook/xsl/xslthl/bourne-hl.xml new file mode 100644 index 0000000..e2cd98d --- /dev/null +++ b/src/main/docbook/xsl/xslthl/bourne-hl.xml @@ -0,0 +1,95 @@ + + + + # + + << + ' + " + - + + + + + " + \ + + + ' + \ + + + + 0x + + + + . + + + + + + if + then + else + elif + fi + case + esac + for + while + until + do + done + + exec + shift + exit + times + break + export + trap + continue + readonly + wait + eval + return + + cd + echo + hash + pwd + read + set + test + type + ulimit + umask + unset + + diff --git a/src/main/docbook/xsl/xslthl/c-hl.xml b/src/main/docbook/xsl/xslthl/c-hl.xml new file mode 100644 index 0000000..176cc37 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/c-hl.xml @@ -0,0 +1,117 @@ + + + + + /** + */ + + + + + + + + /* + */ + + // + + + # + \ + + + + + " + \ + + + ' + \ + + + 0x + ul + lu + u + l + + + + . + + e + ul + lu + u + f + l + + + + auto + _Bool + break + case + char + _Complex + const + continue + default + do + double + else + enum + extern + float + for + goto + if + _Imaginary + inline + int + long + register + restrict + return + short + signed + sizeof + static + struct + switch + typedef + union + unsigned + void + volatile + while + + diff --git a/src/main/docbook/xsl/xslthl/cpp-hl.xml b/src/main/docbook/xsl/xslthl/cpp-hl.xml new file mode 100644 index 0000000..ef83c4f --- /dev/null +++ b/src/main/docbook/xsl/xslthl/cpp-hl.xml @@ -0,0 +1,151 @@ + + + + + /** + */ + + + + + + + + /* + */ + + // + + + # + \ + + + + + " + \ + + + ' + \ + + + 0x + ul + lu + u + l + + + + . + + e + ul + lu + u + f + l + + + + + auto + _Bool + break + case + char + _Complex + const + continue + default + do + double + else + enum + extern + float + for + goto + if + _Imaginary + inline + int + long + register + restrict + return + short + signed + sizeof + static + struct + switch + typedef + union + unsigned + void + volatile + while + + asm + dynamic_cast + namespace + reinterpret_cast + try + bool + explicit + new + static_cast + typeid + catch + false + operator + template + typename + class + friend + private + this + using + const_cast + inline + public + throw + virtual + delete + mutable + protected + true + wchar_t + + diff --git a/src/main/docbook/xsl/xslthl/csharp-hl.xml b/src/main/docbook/xsl/xslthl/csharp-hl.xml new file mode 100644 index 0000000..d57e631 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/csharp-hl.xml @@ -0,0 +1,194 @@ + + + + + /** + */ + + + + /// + + + + /* + */ + + // + + + [ + ] + ( + ) + + + + # + \ + + + + + + @" + " + \ + + + + " + \ + + + ' + \ + + + 0x + ul + lu + u + l + + + + . + + e + ul + lu + u + f + d + m + l + + + + abstract + as + base + bool + break + byte + case + catch + char + checked + class + const + continue + decimal + default + delegate + do + double + else + enum + event + explicit + extern + false + finally + fixed + float + for + foreach + goto + if + implicit + in + int + interface + internal + is + lock + long + namespace + new + null + object + operator + out + override + params + private + protected + public + readonly + ref + return + sbyte + sealed + short + sizeof + stackalloc + static + string + struct + switch + this + throw + true + try + typeof + uint + ulong + unchecked + unsafe + ushort + using + virtual + void + volatile + while + + + + add + alias + from + get + global + group + into + join + orderby + partial + remove + select + set + value + where + yield + + diff --git a/src/main/docbook/xsl/xslthl/css-hl.xml b/src/main/docbook/xsl/xslthl/css-hl.xml new file mode 100644 index 0000000..164c48c --- /dev/null +++ b/src/main/docbook/xsl/xslthl/css-hl.xml @@ -0,0 +1,176 @@ + + + + + /* + */ + + + " + \ + + + + ' + \ + + + + . + + + + @charset + @import + @media + @page + + + + - + azimuth + background-attachment + background-color + background-image + background-position + background-repeat + background + border-collapse + border-color + border-spacing + border-style + border-top + border-right + border-bottom + border-left + border-top-color + border-right-color + border-bottom-color + border-left-color + border-top-style + border-right-style + border-bottom-style + border-left-style + border-top-width + border-right-width + border-bottom-width + border-left-width + border-width + border + bottom + caption-side + clear + clip + color + content + counter-increment + counter-reset + cue-after + cue-before + cue + cursor + direction + display + elevation + empty-cells + float + font-family + font-size + font-style + font-variant + font-weight + font + height + left + letter-spacing + line-height + list-style-image + list-style-position + list-style-type + list-style + margin-right + margin-left + margin-top + margin-bottom + margin + max-height + max-width + min-height + min-width + orphans + outline-color + outline-style + outline-width + outline + overflow + padding-top + padding-right + padding-bottom + padding-left + padding + page-break-after + page-break-before + page-break-inside + pause-after + pause-before + pause + pitch-range + pitch + play-during + position + quotes + richness + right + speak-header + speak-numeral + speak-punctuation + speak + speech-rate + stress + table-layout + text-align + text-decoration + text-indent + text-transform + top + unicode-bidi + vertical-align + visibility + voice-family + volume + white-space + widows + width + word-spacing + z-index + + diff --git a/src/main/docbook/xsl/xslthl/html-hl.xml b/src/main/docbook/xsl/xslthl/html-hl.xml new file mode 100644 index 0000000..5b6761b --- /dev/null +++ b/src/main/docbook/xsl/xslthl/html-hl.xml @@ -0,0 +1,122 @@ + + + + + + + a + abbr + address + area + article + aside + audio + b + base + bdi + blockquote + body + br + button + caption + canvas + cite + code + command + col + colgroup + dd + del + dialog + div + dl + dt + em + embed + fieldset + figcaption + figure + font + form + footer + h1 + h2 + h3 + h4 + h5 + h6 + head + header + hr + html + i + iframe + img + input + ins + kbd + label + legend + li + link + map + mark + menu + menu + meta + nav + noscript + object + ol + optgroup + option + p + param + pre + q + samp + script + section + select + small + source + span + strong + style + sub + summary + sup + table + tbody + td + textarea + tfoot + th + thead + time + title + tr + track + u + ul + var + video + wbr + xmp + + + + + xsl: + + + diff --git a/src/main/docbook/xsl/xslthl/ini-hl.xml b/src/main/docbook/xsl/xslthl/ini-hl.xml new file mode 100644 index 0000000..34c1036 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/ini-hl.xml @@ -0,0 +1,45 @@ + + + + ; + + + ^(\[.+\]\s*)$ + + MULTILINE + + + + ^(.+)(?==) + + MULTILINE + + diff --git a/src/main/docbook/xsl/xslthl/java-hl.xml b/src/main/docbook/xsl/xslthl/java-hl.xml new file mode 100644 index 0000000..f7bb164 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/java-hl.xml @@ -0,0 +1,117 @@ + + + + + /** + */ + + + + /* + */ + + // + + " + \ + + + ' + \ + + + @ + ( + ) + + + 0x + + + + . + e + f + d + l + + + + abstract + boolean + break + byte + case + catch + char + class + const + continue + default + do + double + else + extends + final + finally + float + for + goto + if + implements + import + instanceof + int + interface + long + native + new + package + private + protected + public + return + short + static + strictfp + super + switch + synchronized + this + throw + throws + transient + try + void + volatile + while + + diff --git a/src/main/docbook/xsl/xslthl/javascript-hl.xml b/src/main/docbook/xsl/xslthl/javascript-hl.xml new file mode 100644 index 0000000..99b8a71 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/javascript-hl.xml @@ -0,0 +1,147 @@ + + + + + /* + */ + + // + + " + \ + + + ' + \ + + + 0x + + + + . + e + + + + break + case + catch + continue + default + delete + do + else + finally + for + function + if + in + instanceof + new + return + switch + this + throw + try + typeof + var + void + while + with + + abstract + boolean + byte + char + class + const + debugger + double + enum + export + extends + final + float + goto + implements + import + int + interface + long + native + package + private + protected + public + short + static + super + synchronized + throws + transient + volatile + + + prototype + + Array + Boolean + Date + Error + EvalError + Function + Math + Number + Object + RangeError + ReferenceError + RegExp + String + SyntaxError + TypeError + URIError + + decodeURI + decodeURIComponent + encodeURI + encodeURIComponent + eval + isFinite + isNaN + parseFloat + parseInt + + Infinity + NaN + undefined + + diff --git a/src/main/docbook/xsl/xslthl/json-hl.xml b/src/main/docbook/xsl/xslthl/json-hl.xml new file mode 100644 index 0000000..59b9c48 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/json-hl.xml @@ -0,0 +1,37 @@ + + + # + + " + \ + + + ' + \ + + + @ + ( + ) + + + . + e + f + d + l + + + + true + false + + + { + } + , + [ + ] + + + diff --git a/src/main/docbook/xsl/xslthl/perl-hl.xml b/src/main/docbook/xsl/xslthl/perl-hl.xml new file mode 100644 index 0000000..73d71cc --- /dev/null +++ b/src/main/docbook/xsl/xslthl/perl-hl.xml @@ -0,0 +1,120 @@ + + + + # + + << + ' + " + + + + " + \ + + + ' + \ + + + + 0x + + + + . + + + + + if + unless + while + until + foreach + else + elsif + for + when + default + given + + caller + continue + die + do + dump + eval + exit + goto + last + next + redo + return + sub + wantarray + + caller + import + local + my + package + use + + do + import + no + package + require + use + + bless + dbmclose + dbmopen + package + ref + tie + tied + untie + use + + and + or + not + eq + ne + lt + gt + le + ge + cmp + + diff --git a/src/main/docbook/xsl/xslthl/php-hl.xml b/src/main/docbook/xsl/xslthl/php-hl.xml new file mode 100644 index 0000000..1da25b8 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/php-hl.xml @@ -0,0 +1,154 @@ + + + + + /** + */ + + + + + + + + /* + */ + + // + # + + " + \ + + + + ' + \ + + + + <<< + + + 0x + + + + . + e + + + + and + or + xor + __FILE__ + exception + __LINE__ + array + as + break + case + class + const + continue + declare + default + die + do + echo + else + elseif + empty + enddeclare + endfor + endforeach + endif + endswitch + endwhile + eval + exit + extends + for + foreach + function + global + if + include + include_once + isset + list + new + print + require + require_once + return + static + switch + unset + use + var + while + __FUNCTION__ + __CLASS__ + __METHOD__ + final + php_user_filter + interface + implements + extends + public + private + protected + abstract + clone + try + catch + throw + cfunction + old_function + true + false + + namespace + __NAMESPACE__ + goto + __DIR__ + + + + + ?> + <?php + <?= + + + diff --git a/src/main/docbook/xsl/xslthl/properties-hl.xml b/src/main/docbook/xsl/xslthl/properties-hl.xml new file mode 100644 index 0000000..775f2f1 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/properties-hl.xml @@ -0,0 +1,38 @@ + + + + # + + ^(.+?)(?==|:) + + MULTILINE + + diff --git a/src/main/docbook/xsl/xslthl/python-hl.xml b/src/main/docbook/xsl/xslthl/python-hl.xml new file mode 100644 index 0000000..a467443 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/python-hl.xml @@ -0,0 +1,100 @@ + + + + + + @ + ( + ) + + # + + """ + + + + ''' + + + + " + \ + + + ' + \ + + + 0x + l + + + + . + + e + l + + + + and + del + from + not + while + as + elif + global + or + with + assert + else + if + pass + yield + break + except + import + print + class + exec + in + raise + continue + finally + is + return + def + for + lambda + try + + diff --git a/src/main/docbook/xsl/xslthl/ruby-hl.xml b/src/main/docbook/xsl/xslthl/ruby-hl.xml new file mode 100644 index 0000000..d105640 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/ruby-hl.xml @@ -0,0 +1,109 @@ + + + + # + + << + + + + " + \ + + + %Q{ + } + \ + + + %/ + / + \ + + + ' + \ + + + %q{ + } + \ + + + 0x + + + + . + e + + + + alias + and + BEGIN + begin + break + case + class + def + defined + do + else + elsif + END + end + ensure + false + for + if + in + module + next + nil + not + or + redo + rescue + retry + return + self + super + then + true + undef + unless + until + when + while + yield + + diff --git a/src/main/docbook/xsl/xslthl/sql2003-hl.xml b/src/main/docbook/xsl/xslthl/sql2003-hl.xml new file mode 100644 index 0000000..ac1d5d0 --- /dev/null +++ b/src/main/docbook/xsl/xslthl/sql2003-hl.xml @@ -0,0 +1,565 @@ + + + + -- + + /* + */ + + + ' + + + + U' + ' + + + + B' + ' + + + + N' + ' + + + + X' + ' + + + + . + + e + + + + + + A + ABS + ABSOLUTE + ACTION + ADA + ADMIN + AFTER + ALWAYS + ASC + ASSERTION + ASSIGNMENT + ATTRIBUTE + ATTRIBUTES + AVG + BEFORE + BERNOULLI + BREADTH + C + CARDINALITY + CASCADE + CATALOG_NAME + CATALOG + CEIL + CEILING + CHAIN + CHAR_LENGTH + CHARACTER_LENGTH + CHARACTER_SET_CATALOG + CHARACTER_SET_NAME + CHARACTER_SET_SCHEMA + CHARACTERISTICS + CHARACTERS + CHECKED + CLASS_ORIGIN + COALESCE + COBOL + CODE_UNITS + COLLATION_CATALOG + COLLATION_NAME + COLLATION_SCHEMA + COLLATION + COLLECT + COLUMN_NAME + COMMAND_FUNCTION_CODE + COMMAND_FUNCTION + COMMITTED + CONDITION_NUMBER + CONDITION + CONNECTION_NAME + CONSTRAINT_CATALOG + CONSTRAINT_NAME + CONSTRAINT_SCHEMA + CONSTRAINTS + CONSTRUCTORS + CONTAINS + CONVERT + CORR + COUNT + COVAR_POP + COVAR_SAMP + CUME_DIST + CURRENT_COLLATION + CURSOR_NAME + DATA + DATETIME_INTERVAL_CODE + DATETIME_INTERVAL_PRECISION + DEFAULTS + DEFERRABLE + DEFERRED + DEFINED + DEFINER + DEGREE + DENSE_RANK + DEPTH + DERIVED + DESC + DESCRIPTOR + DIAGNOSTICS + DISPATCH + DOMAIN + DYNAMIC_FUNCTION_CODE + DYNAMIC_FUNCTION + EQUALS + EVERY + EXCEPTION + EXCLUDE + EXCLUDING + EXP + EXTRACT + FINAL + FIRST + FLOOR + FOLLOWING + FORTRAN + FOUND + FUSION + G + GENERAL + GO + GOTO + GRANTED + HIERARCHY + IMPLEMENTATION + INCLUDING + INCREMENT + INITIALLY + INSTANCE + INSTANTIABLE + INTERSECTION + INVOKER + ISOLATION + K + KEY_MEMBER + KEY_TYPE + KEY + LAST + LENGTH + LEVEL + LN + LOCATOR + LOWER + M + MAP + MATCHED + MAX + MAXVALUE + MESSAGE_LENGTH + MESSAGE_OCTET_LENGTH + MESSAGE_TEXT + MIN + MINVALUE + MOD + MORE + MUMPS + NAME + NAMES + NESTING + NEXT + NORMALIZE + NORMALIZED + NULLABLE + NULLIF + NULLS + NUMBER + OBJECT + OCTET_LENGTH + OCTETS + OPTION + OPTIONS + ORDERING + ORDINALITY + OTHERS + OVERLAY + OVERRIDING + PAD + PARAMETER_MODE + PARAMETER_NAME + PARAMETER_ORDINAL_POSITION + PARAMETER_SPECIFIC_CATALOG + PARAMETER_SPECIFIC_NAME + PARAMETER_SPECIFIC_SCHEMA + PARTIAL + PASCAL + PATH + PERCENT_RANK + PERCENTILE_CONT + PERCENTILE_DISC + PLACING + PLI + POSITION + POWER + PRECEDING + PRESERVE + PRIOR + PRIVILEGES + PUBLIC + RANK + READ + RELATIVE + REPEATABLE + RESTART + RETURNED_CARDINALITY + RETURNED_LENGTH + RETURNED_OCTET_LENGTH + RETURNED_SQLSTATE + ROLE + ROUTINE_CATALOG + ROUTINE_NAME + ROUTINE_SCHEMA + ROUTINE + ROW_COUNT + ROW_NUMBER + SCALE + SCHEMA_NAME + SCHEMA + SCOPE_CATALOG + SCOPE_NAME + SCOPE_SCHEMA + SECTION + SECURITY + SELF + SEQUENCE + SERIALIZABLE + SERVER_NAME + SESSION + SETS + SIMPLE + SIZE + SOURCE + SPACE + SPECIFIC_NAME + SQRT + STATE + STATEMENT + STDDEV_POP + STDDEV_SAMP + STRUCTURE + STYLE + SUBCLASS_ORIGIN + SUBSTRING + SUM + TABLE_NAME + TABLESAMPLE + TEMPORARY + TIES + TOP_LEVEL_COUNT + TRANSACTION_ACTIVE + TRANSACTION + TRANSACTIONS_COMMITTED + TRANSACTIONS_ROLLED_BACK + TRANSFORM + TRANSFORMS + TRANSLATE + TRIGGER_CATALOG + TRIGGER_NAME + TRIGGER_SCHEMA + TRIM + TYPE + UNBOUNDED + UNCOMMITTED + UNDER + UNNAMED + USAGE + USER_DEFINED_TYPE_CATALOG + USER_DEFINED_TYPE_CODE + USER_DEFINED_TYPE_NAME + USER_DEFINED_TYPE_SCHEMA + VIEW + WORK + WRITE + ZONE + + ADD + ALL + ALLOCATE + ALTER + AND + ANY + ARE + ARRAY + AS + ASENSITIVE + ASYMMETRIC + AT + ATOMIC + AUTHORIZATION + BEGIN + BETWEEN + BIGINT + BINARY + BLOB + BOOLEAN + BOTH + BY + CALL + CALLED + CASCADED + CASE + CAST + CHAR + CHARACTER + CHECK + CLOB + CLOSE + COLLATE + COLUMN + COMMIT + CONNECT + CONSTRAINT + CONTINUE + CORRESPONDING + CREATE + CROSS + CUBE + CURRENT_DATE + CURRENT_DEFAULT_TRANSFORM_GROUP + CURRENT_PATH + CURRENT_ROLE + CURRENT_TIME + CURRENT_TIMESTAMP + CURRENT_TRANSFORM_GROUP_FOR_TYPE + CURRENT_USER + CURRENT + CURSOR + CYCLE + DATE + DAY + DEALLOCATE + DEC + DECIMAL + DECLARE + DEFAULT + DELETE + DEREF + DESCRIBE + DETERMINISTIC + DISCONNECT + DISTINCT + DOUBLE + DROP + DYNAMIC + EACH + ELEMENT + ELSE + END + END-EXEC + ESCAPE + EXCEPT + EXEC + EXECUTE + EXISTS + EXTERNAL + FALSE + FETCH + FILTER + FLOAT + FOR + FOREIGN + FREE + FROM + FULL + FUNCTION + GET + GLOBAL + GRANT + GROUP + GROUPING + HAVING + HOLD + HOUR + IDENTITY + IMMEDIATE + IN + INDICATOR + INNER + INOUT + INPUT + INSENSITIVE + INSERT + INT + INTEGER + INTERSECT + INTERVAL + INTO + IS + ISOLATION + JOIN + LANGUAGE + LARGE + LATERAL + LEADING + LEFT + LIKE + LOCAL + LOCALTIME + LOCALTIMESTAMP + MATCH + MEMBER + MERGE + METHOD + MINUTE + MODIFIES + MODULE + MONTH + MULTISET + NATIONAL + NATURAL + NCHAR + NCLOB + NEW + NO + NONE + NOT + NULL + NUMERIC + OF + OLD + ON + ONLY + OPEN + OR + ORDER + OUT + OUTER + OUTPUT + OVER + OVERLAPS + PARAMETER + PARTITION + PRECISION + PREPARE + PRIMARY + PROCEDURE + RANGE + READS + REAL + RECURSIVE + REF + REFERENCES + REFERENCING + REGR_AVGX + REGR_AVGY + REGR_COUNT + REGR_INTERCEPT + REGR_R2 + REGR_SLOPE + REGR_SXX + REGR_SXY + REGR_SYY + RELEASE + RESULT + RETURN + RETURNS + REVOKE + RIGHT + ROLLBACK + ROLLUP + ROW + ROWS + SAVEPOINT + SCROLL + SEARCH + SECOND + SELECT + SENSITIVE + SESSION_USER + SET + SIMILAR + SMALLINT + SOME + SPECIFIC + SPECIFICTYPE + SQL + SQLEXCEPTION + SQLSTATE + SQLWARNING + START + STATIC + SUBMULTISET + SYMMETRIC + SYSTEM_USER + SYSTEM + TABLE + THEN + TIME + TIMESTAMP + TIMEZONE_HOUR + TIMEZONE_MINUTE + TO + TRAILING + TRANSLATION + TREAT + TRIGGER + TRUE + UESCAPE + UNION + UNIQUE + UNKNOWN + UNNEST + UPDATE + UPPER + USER + USING + VALUE + VALUES + VAR_POP + VAR_SAMP + VARCHAR + VARYING + WHEN + WHENEVER + WHERE + WIDTH_BUCKET + WINDOW + WITH + WITHIN + WITHOUT + YEAR + + diff --git a/src/main/docbook/xsl/xslthl/yaml-hl.xml b/src/main/docbook/xsl/xslthl/yaml-hl.xml new file mode 100644 index 0000000..a28008e --- /dev/null +++ b/src/main/docbook/xsl/xslthl/yaml-hl.xml @@ -0,0 +1,47 @@ + + + # + + " + \ + + + ' + \ + + + @ + ( + ) + + + . + e + f + d + l + + + + true + false + + + { + } + , + [ + ] + + + + ^(---)$ + + MULTILINE + + + ^(.+?)(?==|:) + + MULTILINE + + diff --git a/streaming/http-to-cassandra/README.adoc b/streaming/http-to-cassandra/README.adoc deleted file mode 100644 index 58ecca1..0000000 --- a/streaming/http-to-cassandra/README.adoc +++ /dev/null @@ -1,295 +0,0 @@ -:sectnums: -= HTTP to Cassandra Demo - -In this demonstration, you will learn how to orchestrate a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from an _HTTP_ endpoint and write the payload to a _Cassandra_ database. - -We will begin by discussing the steps to prep, configure and operationalize Spring Cloud Data Flow's `server` Spring Boot application. We will deploy the `server` using https://github.com/spring-cloud/spring-cloud-dataflow/tree/master/spring-cloud-dataflow-server-local[Local] as well as https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[Cloud Foundry] SPIs (Service Provider Interface) to demonstrate how Spring Cloud Data Flow takes advantage of _dev-sandbox_ and _cloud-native_ platform capabilities respectively. - -== Using Local Server - -=== Prerequisites - -Make sure that you have the following components: - -* Local build of link:https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Running instance of link:http://kafka.apache.org/downloads.html[Kafka] -* Running instance of link:http://cassandra.apache.org/[Apache Cassandra] -* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] to connect to the Cassandra instance. You might have to provide `host`, `port`, `username` and `password` depending on the Cassandra configuration you are using. -* Create a keyspace and a `book` table in Cassandra using: -+ -``` -CREATE KEYSPACE clouddata WITH REPLICATION = { 'class' : 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor': '1' } AND DURABLE_WRITES = true; -USE clouddata; -CREATE TABLE book ( - id uuid PRIMARY KEY, - isbn text, - author text, - title text -); -``` - -=== Running the Sample Locally - -. Launch the locally built `server` application -+ -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar - -``` -+ - -. Connect to Spring Cloud Data Flow's `shell` -+ -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] Kafka binder variant of out-of-the-box applications -+ - -``` -dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven -``` - -+ -. Create the stream -+ -``` -dataflow:>stream create cassandrastream --definition "http --server.port=8888 --spring.cloud.stream.bindings.output.contentType='application/json' | cassandra --ingestQuery='insert into book (id, isbn, title, author) values (uuid(), ?, ?, ?)' --keyspace=clouddata" --deploy - -Created and deployed new stream 'cassandrastream' -``` -NOTE: If Cassandra isn't running on default port on `localhost` or if you need username and password to connect, use one of the following options to specify the necessary connection parameters: `--username='' --password='' --port= --contact-points=` - -+ -. Verify the stream is successfully deployed -+ -``` -dataflow:>stream list -``` -+ -. Notice that `cassandrastream-http` and `cassandrastream-cassandra` link:https://github.com/spring-cloud-stream-app-starters//[Spring Cloud Stream] applications are running as Spring Boot applications within the `server` as a collocated process. -+ - -``` -2015-12-15 15:52:31.576 INFO 18337 --- [nio-9393-exec-1] o.s.c.d.a.s.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:cassandra-sink:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 - Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-284240942697761420/cassandrastream.cassandra -2015-12-15 15:52:31.583 INFO 18337 --- [nio-9393-exec-1] o.s.c.d.a.s.l.OutOfProcessModuleDeployer : deploying module org.springframework.cloud.stream.module:http-source:jar:exec:1.0.0.BUILD-SNAPSHOT instance 0 - Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-data-flow-284240942697761420/cassandrastream.http -``` -+ -. Post sample data pointing to the `http` endpoint: `http://localhost:8888` [`8888` is the `server.port` we specified for the `http` source in this case] -+ -``` -dataflow:>http post --contentType 'application/json' --data '{"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"}' --target http://localhost:8888 -> POST (application/json;charset=UTF-8) http://localhost:8888 {"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"} -> 202 ACCEPTED -``` -+ -. Connect to the Cassandra instance and query the table `clouddata.book` to list the persisted records -+ -``` -select * from clouddata.book; -``` - -+ -. That's it; you're done! - - -== Using Cloud Foundry Server - -=== Prerequisites - -In order to get started, make sure that you have the following components: - -* Cloud Foundry instance -* Local build of https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Local build of Spring Cloud Data Flow's https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[Cloud Foundry Server] -* Running instance of `rabbit` in Cloud Foundry -* Running instance of `cassandra` in Cloud Foundry or from another Cloud provider -* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] to connect to the Cassandra instance. You might have to provide `host`, `port`, `username` and `password` depending on the Cassandra configuration you are using. -* Create a `book` table in your Cassandra keyspace using: -+ -``` -CREATE TABLE book ( - id uuid PRIMARY KEY, - isbn text, - author text, - title text -); -``` - - -=== Running the Sample in Cloud Foundry - -. Verify that CF instance is reachable -+ - -``` -$ cf api -API endpoint: https://api.system.io (API version: 2.43.0) - -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -No apps found -``` -+ -. Follow the instructions to deploy Spring Cloud Data Flow's `server` from https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry/blob/master/README.adoc[Cloud Foundry Server] repo - -+ -. Once you complete step#3 from https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry/blob/master/README.adoc[Cloud Foundry Server] instructions, you'll be able to list the newly deployed `dataflow-server` application in Cloud Foundry -+ - -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` - -+ -. Notice that `dataflow-server` application is started and ready for interaction via `http://dataflow-server.app.io` endpoint - -. Connect to Spring Cloud Data Flow's `shell`. -+ - -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -server-unknown:> -``` -+ -. Connect the `shell` with `server` running at `http://dataflow-server.app.io` -+ - -``` -server-unknown:>dataflow config server http://dataflow-server.app.io -Successfully targeted http://dataflow-server.app.io -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] RabbitMQ binder variant of out-of-the-box applications -+ - -``` -dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven -``` - -+ -. Create the stream -+ - -``` -dataflow:>stream create cassandrastream --definition "http --spring.cloud.stream.bindings.output.contentType='application/json' | cassandra --ingestQuery='insert into book (id, isbn, title, author) values (uuid(), ?, ?, ?)' --username='' --password='' --port= --contact-points= --keyspace=''" --deploy - -Created and deployed new stream 'cassandrastream' -``` -+ -. Verify the stream is successfully deployed -+ -``` -dataflow:>stream list -``` -+ -. Notice that `cassandrastream-http` and `cassandrastream-cassandra` https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as _cloud-native_ (microservice) applications in Cloud Foundry -+ - -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -cassandrastream-cassandra started 1/1 1G 1G cassandrastream-cassandra.app.io -cassandrastream-http started 1/1 1G 1G cassandrastream-http.app.io -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` -+ -. Lookup the `url` for `cassandrastream-http` application from the list above. Post sample data pointing to the `http` endpoint: `` -+ -``` -http post --contentType 'application/json' --data '{"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"}' --target http:// -> POST (application/json;charset=UTF-8) http://cassandrastream-http.app.io {"isbn": "1599869772", "title": "The Art of War", "author": "Sun Tzu"} -> 202 ACCEPTED -``` -+ -. Connect to the Cassandra instance and query the table `book` to list the data inserted -+ -``` -select * from book; -``` - -+ -. Now, let's try to take advantage of Pivotal Cloud Foundry's platform capability. Let's scale the `cassandrastream-http` application from 1 to 3 instances -+ -``` -$ cf scale cassandrastream-http -i 3 -Scaling app cassandrastream-http in org user-dataflow / space development as user... -OK -``` -+ -. Verify App instances (3/3) running successfully -+ -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -cassandrastream-cassandra started 1/1 1G 1G cassandrastream-cassandra.app.io -cassandrastream-http started 3/3 1G 1G cassandrastream-http.app.io -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` -+ -. That's it; you're done! - -:!sectnums: -== Summary - -In this sample, you have learned: - -* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers -* How to use Spring Cloud Data Flow's `shell` -* How to create streaming data pipeline to connect and write to `Cassandra` -* How to scale data microservice applications on `Pivotal Cloud Foundry` diff --git a/streaming/http-to-mysql/README.adoc b/streaming/http-to-mysql/README.adoc deleted file mode 100644 index 904b22e..0000000 --- a/streaming/http-to-mysql/README.adoc +++ /dev/null @@ -1,297 +0,0 @@ -:sectnums: -= HTTP to MySQL Demo - -In this demonstration, you will learn how to orchestrate a data pipeline using http://cloud.spring.io/spring-cloud-dataflow/[Spring Cloud Data Flow] to consume data from an `http` endpoint and write to MySQL database using `jdbc` sink. - -We will begin by discussing the steps to prep, configure and operationalize Spring Cloud Data Flow's `server` Spring Boot application. We will deploy the `server` using https://github.com/spring-cloud/spring-cloud-dataflow/tree/master/spring-cloud-dataflow-server-local[Local] as well as https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[Cloud Foundry] SPIs (Service Provider Interface) to demonstrate how Spring Cloud Data Flow takes advantage of _dev-sandbox_ and _cloud-native_ platform capabilities, respectively. - -== Using Local Server - -=== Prerequisites - -Make sure that you have the following components: - -* Local build of https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Running instance of link:http://kafka.apache.org/downloads.html[Kafka] -* Running instance of link:http://www.mysql.com/[MySQL] -* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] or link:https://www.dbvis.com/[DbVisualizer] -* Create the `test` database with a `names` table (in MySQL) using: -+ -``` -CREATE DATABASE test; -USE test; -CREATE TABLE names -( - name varchar(255) -); -``` - -=== Running the Sample Locally - -. Launch the locally built `server` -+ - -``` -$ cd -$ java -jar spring-cloud-dataflow-server-local/target/spring-cloud-dataflow-server-local-.jar - -``` -+ - -. Connect to Spring Cloud Data Flow's `shell` -+ - -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] Kafka binder variant of out-of-the-box applications -+ - -``` -dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-kafka-10-maven -``` - -+ -. Create the stream -+ -``` -dataflow:>stream create --name mysqlstream --definition "http --server.port=8787 | jdbc --tableName=names --columns=name --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver --spring.datasource.url='jdbc:mysql://localhost:3306/test'" --deploy - -Created and deployed new stream 'mysqlstream' -``` -NOTE: If MySQL isn't running on default port on `localhost` or if you need username and password to connect, use one of the following options to specify the necessary connection parameters: `--spring.datasource.url='jdbc:mysql://:/' --spring.datasource.username= --spring.datasource.password=` - -+ -. Verify the stream is successfully deployed -+ -``` -dataflow:>stream list -``` -+ -. Notice that `mysqlstream-http` and `mysqlstream-jdbc` https://github.com/spring-cloud-stream-app-starters//[Spring Cloud Stream] applications are running as Spring Boot applications within the Local `server` as collocated processes. -+ - -``` -2016-05-03 09:29:55.918 INFO 65162 --- [nio-9393-exec-3] o.s.c.d.spi.local.LocalAppDeployer : deploying app mysqlstream.jdbc instance 0 - Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-dataflow-6850863945840320040/mysqlstream1-1462292995903/mysqlstream.jdbc -2016-05-03 09:29:55.939 INFO 65162 --- [nio-9393-exec-3] o.s.c.d.spi.local.LocalAppDeployer : deploying app mysqlstream.http instance 0 - Logs will be in /var/folders/c3/ctx7_rns6x30tq7rb76wzqwr0000gp/T/spring-cloud-dataflow-6850863945840320040/mysqlstream-1462292995934/mysqlstream.http -``` - -. Post sample data pointing to the `http` endpoint: `http://localhost:8787` [`8787` is the `server.port` we specified for the `http` source in this case] - -+ -``` -dataflow:>http post --contentType 'application/json' --target http://localhost:8787 --data "{\"name\": \"Foo\"}" -> POST (application/json;charset=UTF-8) http://localhost:8787 {"name": "Spring Boot"} -> 202 ACCEPTED -``` -+ -. Connect to the MySQL instance and query the table `test.names` to list the new rows: -+ -``` -select * from test.names; -``` -+ -. That's it; you're done! - -== Using Cloud Foundry Server - -=== Prerequisites - -In order to get started, make sure that you have the following components: - -* Cloud Foundry instance -* Local build of https://github.com/spring-cloud/spring-cloud-dataflow[Spring Cloud Data Flow] -* Local build of Spring Cloud Data Flow's https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry[Cloud Foundry Server] -* Running instance of `rabbit` in Cloud Foundry -* Running instance of `mysql` in Cloud Foundry -* A database utility tool such as link:http://dbeaver.jkiss.org/[DBeaver] or link:https://www.dbvis.com/[DbVisualizer] -* Create the `names` table (in MySQL) using: -+ -``` -CREATE TABLE names -( - name varchar(255) -); -``` - -=== Running the Sample in Cloud Foundry - -. Verify that CF instance is reachable -+ - -``` -$ cf api -API endpoint: https://api.system.io (API version: 2.43.0) - -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -No apps found -``` -+ -. Follow the instructions to deploy Spring Cloud Data Flow's `server` from https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry/blob/master/README.adoc[Cloud Foundry Server] repo - -+ -. Once you complete step#3 from https://github.com/spring-cloud/spring-cloud-dataflow-server-cloudfoundry/blob/master/README.adoc[Cloud Foundry Server] instructions, you'll be able to list the newly deployed `dataflow-server` application in Cloud Foundry -+ - -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` - -+ -. Notice that `dataflow-server` application is started and ready for interaction via `http://dataflow-server.app.io` endpoint - -. Connect to Spring Cloud Data Flow's `shell` -+ - -``` -$ cd -$ java -jar spring-cloud-dataflow-shell/target/spring-cloud-dataflow-shell-.jar - - ____ ____ _ __ - / ___| _ __ _ __(_)_ __ __ _ / ___| | ___ _ _ __| | - \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | - ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | - |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| - ____ |_| _ __|___/ __________ - | _ \ __ _| |_ __ _ | ___| | _____ __ \ \ \ \ \ \ - | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / \ \ \ \ \ \ - | |_| | (_| | || (_| | | _| | | (_) \ V V / / / / / / / - |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ /_/_/_/_/_/ - - - -Welcome to the Spring Cloud Data Flow shell. For assistance hit TAB or type "help". -server-unknown:> -``` -+ -. Connect the `shell` with `server` running at `http://dataflow-server.app.io` -+ - -``` -server-unknown:>dataflow config server http://dataflow-server.app.io -Successfully targeted http://dataflow-server.app.io -dataflow:>version - -``` - -+ -. https://github.com/spring-cloud/spring-cloud-dataflow/blob/master/spring-cloud-dataflow-docs/src/main/asciidoc/streams.adoc#register-a-stream-app[Register] RabbitMQ binder variant of out-of-the-box applications -+ - -``` -dataflow:>app import --uri http://bit.ly/Bacon-RELEASE-stream-applications-rabbit-maven -``` - -+ -. Create the stream -+ - -``` -dataflow:>stream create --name mysqlstream --definition "http | jdbc --tableName=names --columns=name" -Created new stream 'mysqlstream' - -dataflow:>stream deploy --name mysqlstream --properties "app.jdbc.spring.cloud.deployer.cloudfoundry.services=mysql" -Deployed stream 'mysqlstream' - -``` -+ - -NOTE: By supplying `mysql` property through `app.jdbc.spring.cloud.deployer.cloudfoundry.services` token, we are deploying the stream with `jdbc-sink` to automatically bind to `mysql` service and only this application in the stream gets the service binding. This also eliminates the requirement to supply `datasource` credentials in stream definition. -+ -. Verify the stream is successfully deployed -+ -``` -dataflow:>stream list -``` -+ -. Notice that `mysqlstream-http` and `mysqlstream-jdbc` https://github.com/spring-cloud-stream-app-starters/[Spring Cloud Stream] applications are running as _cloud-native_ (microservice) applications in Cloud Foundry -+ - -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -mysqlstream-http started 1/1 1G 1G mysqlstream-http.app.io -mysqlstream-jdbc started 1/1 1G 1G mysqlstream-jdbc.app.io -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` -+ -. Lookup the `url` for `mysqlstream-http` application from the list above. Post sample data pointing to the `http` endpoint: `` -+ -``` -http post --contentType 'application/json' --target http://mysqlstream-http.app.io --data "{\"name\": \"Bar"}" -> POST (application/json;charset=UTF-8) http://mysqlstream-http.app.io {"name": "Bar"} -> 202 ACCEPTED -``` -+ -. Connect to the MySQL instance and query the table `names` to list the new rows: -+ -``` -select * from names; -``` - -+ -. Now, let's take advantage of Pivotal Cloud Foundry's platform capability. Let's scale the `mysqlstream-http` application from 1 to 3 instances -+ -``` -$ cf scale mysqlstream-http -i 3 -Scaling app mysqlstream-http in org user-dataflow / space development as user... -OK -``` -+ -. Verify App instances (3/3) running successfully -+ -``` -$ cf apps -Getting apps in org user-dataflow / space development as user... -OK - -name requested state instances memory disk urls -mysqlstream-http started 3/3 1G 1G mysqlstream-http.app.io -mysqlstream-jdbc started 1/1 1G 1G mysqlstream-jdbc.app.io -dataflow-server started 1/1 1G 1G dataflow-server.app.io -``` -+ -. That's it; you're done! - -:!sectnums: -== Summary - -In this sample, you have learned: - -* How to use Spring Cloud Data Flow's `Local` and `Cloud Foundry` servers -* How to use Spring Cloud Data Flow's `shell` -* How to create streaming data pipeline to connect and write to `MySQL` -* How to scale data microservice applications on `Pivotal Cloud Foundry`