├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── babel-camel ├── babel-camel-core │ ├── build.sbt │ ├── pom.xml │ └── src │ │ ├── main │ │ └── scala │ │ │ └── io │ │ │ └── xtech │ │ │ └── babel │ │ │ └── camel │ │ │ ├── CamelDSL.scala │ │ │ ├── EnricherDSL.scala │ │ │ ├── ErrorHandlingDSL.scala │ │ │ ├── HandlerDSL.scala │ │ │ ├── LogDSL.scala │ │ │ ├── MarshallerDSL.scala │ │ │ ├── MulticastWithAggregationDSL.scala │ │ │ ├── RecipientListDSL.scala │ │ │ ├── ResequencerDSL.scala │ │ │ ├── RouteConfigurationDSL.scala │ │ │ ├── RouteIdDSL.scala │ │ │ ├── SortDSL.scala │ │ │ ├── ThrottlerDSL.scala │ │ │ ├── TransactionDSL.scala │ │ │ ├── TransformationDSL.scala │ │ │ ├── ValidationDSL.scala │ │ │ ├── WireTapDSL.scala │ │ │ ├── builder │ │ │ ├── RouteBuilder.scala │ │ │ └── SpringRouteBuilder.scala │ │ │ ├── model │ │ │ ├── Aggregation.scala │ │ │ ├── AggregationStrategy.scala │ │ │ ├── CamelMessage.scala │ │ │ ├── CamelSink.scala │ │ │ ├── CamelSource.scala │ │ │ ├── EmptyDefinition.scala │ │ │ ├── EnrichDefinition.scala │ │ │ ├── ErrorHandling.scala │ │ │ ├── ErrorHandlingRouteDefinition.scala │ │ │ ├── Expression.scala │ │ │ ├── LogDefinition.scala │ │ │ ├── MarshallerDefinition.scala │ │ │ ├── MulticastAggregationDefinition.scala │ │ │ ├── Predicate.scala │ │ │ ├── RecipientListDefinition.scala │ │ │ ├── ResequencerDefinition.scala │ │ │ ├── RouteConfigurationDefinition.scala │ │ │ ├── RouteIdDefinition.scala │ │ │ ├── SortDefinition.scala │ │ │ ├── ThrottlerDefinition.scala │ │ │ ├── TransactionDefinition.scala │ │ │ ├── ValidationDefinition.scala │ │ │ └── WireTapDefinition.scala │ │ │ └── parsing │ │ │ ├── Aggregation.scala │ │ │ ├── Basics.scala │ │ │ ├── CamelParsing.scala │ │ │ ├── Enricher.scala │ │ │ ├── Handler.scala │ │ │ ├── Log.scala │ │ │ ├── Marshaller.scala │ │ │ ├── RecipientList.scala │ │ │ ├── Resequencer.scala │ │ │ ├── RouteConfiguration.scala │ │ │ ├── RouteId.scala │ │ │ ├── Sort.scala │ │ │ ├── Throttler.scala │ │ │ ├── Transaction.scala │ │ │ ├── Transformation.scala │ │ │ ├── Validation.scala │ │ │ ├── WireTap.scala │ │ │ └── Wrapper.scala │ │ └── test │ │ ├── java │ │ └── io │ │ │ └── xtech │ │ │ └── babel │ │ │ └── camel │ │ │ └── javaprocessors │ │ │ └── JavaProcessors.java │ │ ├── resources │ │ ├── META-INF │ │ │ └── spring │ │ │ │ ├── context-constructor-injection.xml │ │ │ │ ├── context-setter-injection.xml │ │ │ │ └── context.xml │ │ ├── log4j.properties │ │ └── schema.sql │ │ └── scala │ │ └── io │ │ └── xtech │ │ └── babel │ │ └── camel │ │ ├── AggregateSpec.scala │ │ ├── AsSpec.scala │ │ ├── CamelDSLSpec.scala │ │ ├── CamelMessageSpec.scala │ │ ├── CompilationSpec.scala │ │ ├── EnricherSpec.scala │ │ ├── HandlerSpec.scala │ │ ├── IdSpec.scala │ │ ├── LogSpec.scala │ │ ├── MarshallerSpec.scala │ │ ├── MockSpec.scala │ │ ├── MulticastSpec.scala │ │ ├── RecipientListSpec.scala │ │ ├── RequireAsSpec.scala │ │ ├── ResequencerSpec.scala │ │ ├── RouteConfigurationSpec.scala │ │ ├── RouteIdSpec.scala │ │ ├── SortSpec.scala │ │ ├── SplitAggregateSpec.scala │ │ ├── SplitFilterSpec.scala │ │ ├── SplitSpec.scala │ │ ├── ThrottlerSpec.scala │ │ ├── TransactionSpec.scala │ │ ├── TransformerSpec.scala │ │ ├── ValidationSpec.scala │ │ ├── WireTapSpec.scala │ │ ├── XMLSpec.scala │ │ ├── builder │ │ ├── RouteBuilderSpec.scala │ │ ├── spring │ │ │ └── MyRouteBuilder.scala │ │ └── springinjection │ │ │ └── SetterInjectionRouteBuilder.scala │ │ ├── choice │ │ ├── ComplexChoiceSpec.scala │ │ ├── DemoSpec.scala │ │ └── SimpleChoiceSpec.scala │ │ ├── sample │ │ ├── SamplePhilosophySpec.scala │ │ └── SampleSpec.scala │ │ └── test │ │ ├── SpecsContexts.scala │ │ └── SpringSpecification.scala └── babel-camel-mock │ ├── build.sbt │ └── src │ ├── main │ └── scala │ │ └── io │ │ └── xtech │ │ └── babel │ │ └── camel │ │ └── mock │ │ ├── MockDSL.scala │ │ └── package.scala │ └── test │ └── scala │ └── io │ └── xtech │ └── babel │ └── camel │ └── MockSpec.scala ├── babel-doc ├── CLA.md ├── Makefile ├── documentation.sh ├── generate-pdf.sh ├── images │ ├── architecture-camel.png │ ├── architecture.png │ ├── logo-without-pole.png │ ├── logo.png │ └── vectorial │ │ ├── architecture-camel.svg │ │ ├── architecture.svg │ │ ├── logo-without-pole.svg │ │ ├── logo.idraw │ │ ├── logo.svg │ │ └── modules.svg ├── make.bat └── source │ ├── .gitignore │ ├── .sphinx │ └── exts │ │ ├── .gitignore │ │ └── includecode.py │ ├── .static │ ├── default.css │ ├── eip.png │ ├── lambda.png │ ├── language.png │ ├── modular.png │ ├── osgi.png │ └── type.png │ ├── .templates │ └── layout.html │ ├── _themes │ └── bootstrap │ ├── architecture.rst │ ├── camel │ ├── basics.rst │ ├── errormanagement.rst │ ├── mock.rst │ ├── routing.rst │ ├── samples.rst │ ├── spring.rst │ └── transformation.rst │ ├── cameluserguide.rst │ ├── conf.py │ ├── dev │ ├── contribute.rst │ ├── development.rst │ ├── extension.rst │ ├── installation.rst │ ├── legal.rst │ └── structure.rst │ ├── devguide.rst │ ├── grammar-diagrams │ ├── handler-1.png │ ├── handler-1.svg │ ├── handler-2.png │ ├── handler-2.svg │ ├── handler-3.png │ ├── handler-3.svg │ ├── handler-4.png │ └── handler-4.svg │ ├── grammar.g │ ├── grammar │ └── handler.grammar │ ├── index.rst │ ├── opinion.rst │ └── quickstartguide.rst ├── babel-fish ├── build.sbt └── src │ ├── main │ └── scala │ │ └── io │ │ └── xtech │ │ └── babel │ │ └── fish │ │ ├── DSL.scala │ │ ├── DSLHelper.scala │ │ ├── JVMLanguage.scala │ │ ├── NamingStrategy.scala │ │ ├── model │ │ ├── AggregationDefinition.scala │ │ ├── BaseDefinition.scala │ │ ├── ChoiceDefinition.scala │ │ ├── FilterDefinition.scala │ │ ├── FromDefinition.scala │ │ ├── Model.scala │ │ ├── ScopeDefinition.scala │ │ ├── SplitterDefinition.scala │ │ ├── StepDefinition.scala │ │ └── TransformerDefinition.scala │ │ └── parsing │ │ ├── Parser.scala │ │ └── ParsingException.scala │ └── test │ ├── resources │ └── log4j.properties │ └── scala │ └── io │ └── xtech │ └── babel │ └── fish │ ├── AggregateDSLSpec.scala │ ├── DSLSpec.scala │ ├── SplitterDSLSpec.scala │ └── Test.scala ├── build.sbt ├── notes ├── 0.6.0.markdown ├── 0.7.0.markdown └── about.markdown ├── pom.xml ├── project ├── Build.scala ├── Dependencies.scala ├── Formatting.scala ├── Publish.scala └── plugins.sbt └── src └── main └── ls ├── 0.6.json ├── 0.7.0.json └── 0.8.0.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.ipr 2 | *.iml 3 | .idea 4 | target/ 5 | build/ 6 | *.aux 7 | *.nav 8 | *.toc 9 | *.out 10 | *.snm 11 | *.log 12 | *.pdf 13 | atlassian-ide-plugin.xml 14 | .jira-url 15 | .classpath 16 | .project 17 | .settings 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | 3 | scala: 4 | - 2.10.5 5 | - 2.11.6 6 | 7 | sbt_args: -no-colors 8 | 9 | env: 10 | global: 11 | - JVM_OPTS="-XX:MaxPermSize=256m -Xmx1024m -XX:ReservedCodeCacheSize=128m" 12 | 13 | script: sbt ++$TRAVIS_SCALA_VERSION clean coverage test 14 | 15 | after_success: 16 | - sbt coverageReport coverageAggregate 17 | - sbt coveralls 18 | - sbt codacyCoverage 19 | 20 | 21 | jdk: 22 | - oraclejdk7 23 | - openjdk7 24 | - oraclejdk8 25 | 26 | notifications: 27 | email: 28 | recipients: 29 | - github@crossing-tech.com 30 | on_success: never #default: change 31 | on_failure: always #default: always 32 | irc: "irc.codehaus.org#babel" 33 | 34 | sudo: false 35 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 Crossing-Tech SA 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Babel 2 | ===== 3 | 4 | ### Build Status ### 5 | 6 | Master: [![Build Status](https://travis-ci.org/Crossing-Tech/babel.svg?branch=master)](https://travis-ci.org/Crossing-Tech/babel) [![Coverage Status](https://coveralls.io/repos/Crossing-Tech/babel/badge.svg?branch=master)](https://coveralls.io/r/Crossing-Tech/babel?branch=master) 7 | 8 | ### Description ### 9 | 10 | Babel is an efficient way to write your integration solution. It stands as a generic Domain Specific Language (DSL) especially made for integration duties. 11 | 12 | Implementation of Babel have been done for [Apache Camel](http://camel.apache.org "Apache Camel website"). 13 | 14 | ### Communication ### 15 | 16 | * [Babel documentation](http://crossing-tech.github.io/babel) 17 | * Google Group [Babel User List](https://groups.google.com/forum/#!forum/babel-user) 18 | * IRC: irc.codehaus.org:6697 #babel 19 | 20 | ### Project Requirements ### 21 | * Operating System: GNU/Linux, Mac OS X, Windows 22 | * Java VM: Oracle JDK 6 23 | * Sbt 0.13 24 | 25 | ### Project main dependencies ### 26 | * Scala library (2.14.4) 27 | * Apache camel (2.15.0) 28 | 29 | #### Backward compatibity #### 30 | 31 | Babel provides also artifacts for earlier versions of Apache Camel: 32 | 33 | To use Apache Camel version 2.12.x, use Babel with version 0.7.0-camel-2.12.4 34 | 35 | ### Quick Sbt Start Guide ### 36 | 37 | #### Add Babel to an existing sbt project #### 38 | 39 | To include Babel Camel in an existing Sbt project, just add the following dependency in your configuration file (replacing BABEL_VERSION by the version you want to use): 40 | 41 | ```libraryDependencies += "io.xtech.babel" %% "babel-camel-core" % "BABEL_VERSION"``` 42 | 43 | If you are not installing the Babel project locally, you would also need to specify the Sonatype Snapshot repository in your project configuration: 44 | 45 | ```resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"``` 46 | 47 | ### Quick Maven Start Guide ### 48 | 49 | #### Add Babel to an existing Maven project #### 50 | 51 | To include Babel Camel in an existing Maven project, just add the following dependency in your pom.xml file (replacing BABEL_VERSION by the version you want to use): 52 | 53 | ```xml 54 | 55 | io.xtech.babel 56 | babel-camel-core 57 | BABEL_VERSION 58 | 59 | ``` 60 | 61 | 62 | ### Quick Installation Guide ### 63 | 64 | #### Build Babel from sources with Sbt #### 65 | ``` 66 | #in a regular shell: 67 | git clone https://github.com/crossing-tech/babel.git 68 | cd babel 69 | export SBT_OPTS="-XX:MaxPermSize=256m -Xmx1024m" 70 | sbt test publish-local 71 | #or if you want to publish artifacts for maven 72 | sbt test publish-m2 73 | ``` 74 | 75 | #### Build Babel from sources with Maven #### 76 | ``` 77 | #in a regular shell: 78 | git clone https://github.com/crossing-tech/babel.git 79 | cd babel 80 | export MAVEN_OPTS="-XX:MaxPermSize=256m -Xmx1024m" 81 | mvn -Parchetype install 82 | ``` 83 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/build.sbt: -------------------------------------------------------------------------------- 1 | 2 | organization := "io.xtech.babel" 3 | 4 | name := "babel-camel-core" 5 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/ErrorHandlingDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.ErrorHandlingRouteDefinition 12 | import io.xtech.babel.fish.{ BaseDSL, NoDSL } 13 | 14 | import scala.language.implicitConversions 15 | import scala.reflect.ClassTag 16 | 17 | /** 18 | * Adds the routeId keyword to the FromDSL (start of the route). 19 | */ 20 | private[camel] class ErrorHandlingDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) { 21 | 22 | /** 23 | * the sub keyword. 24 | * @param errorHandlingChannel a given id for a new sub route. 25 | * @return the possibility to add other steps to the current DSL. 26 | */ 27 | def handlingRoute(errorHandlingChannel: String): NoDSL = { 28 | //todo use a macro to ensure id is correct string 29 | require(Option(errorHandlingChannel).exists(_.trim.length > 0), "errorHandling Route can neither be null nor empty") 30 | 31 | val definition = ErrorHandlingRouteDefinition(errorHandlingChannel) 32 | baseDsl.step.next = Some(definition) 33 | new NoDSL {} 34 | 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/MarshallerDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model._ 12 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL } 13 | import org.apache.camel.spi.DataFormat 14 | 15 | import scala.language.implicitConversions 16 | import scala.reflect.ClassTag 17 | 18 | /** 19 | * DSL adding the marshalling keywords. 20 | */ 21 | private[camel] class MarshallerDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 22 | 23 | /** 24 | * The marshal keyword. 25 | * Defines how to transform inputs using a reference to a Bean. 26 | * @param ref reference of the bean used for the transformation 27 | * @return the possibility to add other steps to the current DSL 28 | */ 29 | def marshal(ref: String): BaseDSL[Any] = { 30 | 31 | val props = MarshallerReference(ref) 32 | MarshallerDefinition(props) 33 | 34 | } 35 | 36 | /** 37 | * The marshal keyword. 38 | * Defines how to transform inputs using a dataFormat. 39 | * @param dataFormat used for the transformation 40 | * @return the possibility to add other steps to the current DSL 41 | */ 42 | def marshal(dataFormat: DataFormat): BaseDSL[Any] = { 43 | 44 | val props = new MarshallerInstance(dataFormat) 45 | MarshallerDefinition(props) 46 | 47 | } 48 | 49 | /** 50 | * The unmarshal keyword. 51 | * Defines how to transform inputs using a reference to a Bean. 52 | * @param ref reference of the bean used for the transformation 53 | * @return the possibility to add other steps to the current DSL 54 | */ 55 | def unmarshal(ref: String): BaseDSL[Any] = { 56 | 57 | val props = new UnmarshallerReference(ref) 58 | MarshallerDefinition(props) 59 | 60 | } 61 | 62 | /** 63 | * The unmarshal keyword. 64 | * Defines how to transform inputs using a dataFormat. 65 | * @param dataFormat used for the transformation 66 | * @return the possibility to add other steps to the current DSL 67 | */ 68 | def unmarshal(dataFormat: DataFormat): BaseDSL[Any] = { 69 | 70 | val props = new UnmarshallerInstance(dataFormat) 71 | new MarshallerDefinition(props) 72 | 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/MulticastWithAggregationDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.MulticastAggregationDefinition 12 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL } 13 | import org.apache.camel.processor.aggregate.AggregationStrategy 14 | 15 | import scala.language.implicitConversions 16 | import scala.reflect.ClassTag 17 | 18 | /** 19 | * Adds the wiretap keyword to the BaseDSL. 20 | */ 21 | private[camel] class MulticastWithAggregationDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 22 | 23 | /** 24 | * Multicast configuration. Defines how a multicast aggregates its messages. 25 | * @param aggregate the AggregationStrategy used to aggregates messages output by the multicast branches. 26 | * @return the possibility to add other steps to the current DSL 27 | */ 28 | def withAggregation(aggregate: AggregationStrategy): BaseDSL[I] = MulticastAggregationDefinition[I](aggregate) 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/RecipientListDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.RecipientListDefinition 12 | import io.xtech.babel.camel.parsing.RecipientlistDSL 13 | import io.xtech.babel.fish.model.{ Expression, Message } 14 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL, MessageExpression } 15 | 16 | import scala.reflect.ClassTag 17 | 18 | private[camel] class RecipientListDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 19 | 20 | /** 21 | * The recipientList defines, using a function, the endpoits where the inputs should be routed. 22 | * @param function which defines the targeted endpoints 23 | * @tparam E 24 | * @return the possibility to add other steps to the current DSL 25 | */ 26 | def recipientList[E](function: Message[I] => E): RecipientlistDSL[I] = { 27 | 28 | val definition = RecipientListDefinition(MessageExpression(function)) 29 | baseDsl.step.next = Some(definition) 30 | new RecipientlistDSL[I](definition) 31 | } 32 | 33 | /** 34 | * The recipientList defines, using an expression, the endpoits where the inputs should be routed. 35 | * @param expression which defines the targeted endpoints 36 | * @tparam E type the targets (endpoints) 37 | * @return the possibility to add other steps to the current DSL 38 | */ 39 | def recipientList[E](expression: Expression[I, E]): RecipientlistDSL[I] = { 40 | 41 | val definition = RecipientListDefinition(expression) 42 | baseDsl.step.next = Some(definition) 43 | new RecipientlistDSL[I](definition) 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/ResequencerDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.ResequencerDefinition 12 | import io.xtech.babel.fish.model.{ Expression, Message } 13 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL, MessageExpression } 14 | import org.apache.camel.model.config.ResequencerConfig 15 | 16 | import scala.language.implicitConversions 17 | import scala.reflect.ClassTag 18 | 19 | /** 20 | * DSL adding the resequence keyword. 21 | */ 22 | private[camel] class ResequencerDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 23 | 24 | /** 25 | * The resequencer keyword in the dsl. 26 | * @param function on what part of the message the comparaison are done. 27 | * @param resequencerConfig an implementation of ResequencerConfig 28 | * @tparam E the type of the message, header, or a piece of the message 29 | * @return the possibility to add other steps to the current DSL 30 | */ 31 | def resequence[E](function: Message[I] => E, resequencerConfig: ResequencerConfig): BaseDSL[I] = { 32 | 33 | ResequencerDefinition(MessageExpression(function), resequencerConfig) 34 | 35 | } 36 | 37 | /** 38 | * The resequencer keyword in the dsl. 39 | * @param expression on what part of the message the comparaison are done. 40 | * @param resequencerConfig an implementation of ResequencerConfig 41 | * @tparam E the type of the message, header, or a piece of the message 42 | * @return the possibility to add other steps to the current DSL 43 | */ 44 | def resequence[E](expression: Expression[I, E], resequencerConfig: ResequencerConfig): BaseDSL[I] = { 45 | 46 | ResequencerDefinition(expression, resequencerConfig) 47 | 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/RouteIdDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.{ IdDefinition, RouteIdDefinition } 12 | import io.xtech.babel.fish.{ BaseDSL, BaseDSL2FromDSL, FromDSL } 13 | 14 | import scala.language.implicitConversions 15 | import scala.reflect.ClassTag 16 | 17 | /** 18 | * Adds the routeId keyword to the FromDSL (start of the route). 19 | */ 20 | private[camel] class RouteIdDSL[I: ClassTag](protected val baseDsl: FromDSL[I]) extends BaseDSL2FromDSL[I] { 21 | 22 | /** 23 | * the routeId keyword. 24 | * @param id a given id for a route. 25 | * @return the possibility to add other steps to the current DSL 26 | */ 27 | def routeId(id: String): FromDSL[I] = { 28 | require(Option(id).exists(_.trim.length > 0), "routeId can neither be null nor empty") 29 | 30 | RouteIdDefinition(id) 31 | } 32 | } 33 | 34 | private[camel] class IdDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends BaseDSL2FromDSL[I] { 35 | /** 36 | * the id keyword. 37 | * @param id a given id for the previous eip. 38 | * @return the possibility to add other steps to the current DSL 39 | */ 40 | def id(id: String): BaseDSL[I] = { 41 | require(Option(id).exists(_.trim.length > 0), "id can neither be null nor empty") 42 | 43 | IdDefinition(id) 44 | 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/SortDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import java.util.{ Comparator, List => JList } 12 | 13 | import io.xtech.babel.camel.model.SortDefinition 14 | import io.xtech.babel.fish.model.{ Expression, Message } 15 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL, MessageExpression } 16 | 17 | import scala.collection.mutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | /** 22 | * Adds the sort keyword to the BaseDSL. 23 | */ 24 | private[camel] class SortDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 25 | 26 | /** 27 | * The sort keyword. 28 | * @param function what element of the message is sorted. 29 | * @param comparator how are the element sorted. 30 | * @tparam O the output type. 31 | * @return the possibility to add other steps to the current DSL 32 | */ 33 | def sort[O: ClassTag](function: Message[I] => mutable.IndexedSeq[O], comparator: Comparator[O]): BaseDSL[JList[O]] = { 34 | 35 | SortDefinition(MessageExpression(function), Some(comparator)) 36 | 37 | } 38 | 39 | /** 40 | * The sort keyword. This keyword use the default camel comparator. 41 | * @param function what element of the message is sorted. 42 | * @tparam O the output type. 43 | * @return the possibility to add other steps to the current DSL 44 | */ 45 | def sort[O: ClassTag](function: Message[I] => mutable.IndexedSeq[O]): BaseDSL[JList[O]] = { 46 | 47 | SortDefinition(MessageExpression(function), None) 48 | 49 | } 50 | 51 | def sort[O: ClassTag, C](expression: Expression[I, O], comparator: Comparator[C]): BaseDSL[JList[O]] = { 52 | 53 | SortDefinition(expression, Some(comparator)) 54 | 55 | } 56 | 57 | def sort[O: ClassTag](expression: Expression[I, O]): BaseDSL[JList[O]] = { 58 | 59 | SortDefinition(expression, None) 60 | 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/ThrottlerDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.{ ThrottlerDefinitionExpression, ThrottlerDefinitionLong } 12 | import io.xtech.babel.fish.model.Message 13 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL, MessageExpression } 14 | 15 | import scala.reflect.ClassTag 16 | 17 | /** 18 | * DSL adding the throttle keyword 19 | */ 20 | class ThrottlerDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 21 | 22 | /** 23 | * The throttle keyword. Defines the maximal rate that may be use in order to avoid overloading of the rest of the route 24 | * @param perSecond number of allowed messages in 1 second 25 | * @return the possibility to add other steps to the current DSL 26 | */ 27 | def throttle(perSecond: Long): BaseDSL[I] = ThrottlerDefinitionLong(perSecond) 28 | 29 | /** 30 | * The throttle keyword. Defines the maximal rate that may be use in order to avoid overloading of the rest of the route 31 | * @param perSecond number of allowed messages in 1 second using a function 32 | * @return the possibility to add other steps to the current DSL 33 | */ 34 | def throttle(perSecond: Message[I] => Long): BaseDSL[I] = ThrottlerDefinitionExpression(MessageExpression(perSecond)) 35 | } 36 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/TransactionDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.TransactionDefinition 12 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL } 13 | 14 | import scala.language.implicitConversions 15 | import scala.reflect.ClassTag 16 | 17 | /** 18 | * Adds transaction in the Bable Camel DSL. 19 | */ 20 | private[camel] class TransactionDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 21 | 22 | /** 23 | * The transacted keyword. Defines that the exchange flow goes through a transaction. 24 | * @return the possibility to add other steps to the current DSL 25 | */ 26 | def transacted(): BaseDSL[I] = TransactionDefinition() 27 | 28 | /** 29 | * The transacted keyword. Defines that the exchange flow goes through a transaction. 30 | * @param ref the bean which is responsible for the transaction. 31 | * @return the possibility to add other steps to the current DSL 32 | */ 33 | //todo: missing tests for transacted 34 | def transacted(ref: String): BaseDSL[I] = TransactionDefinition(Some(ref)) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/TransformationDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.{ BeanClassExpression, BeanNameExpression, BeanObjectExpression } 12 | import io.xtech.babel.fish.model.TransformerDefinition 13 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL } 14 | 15 | import scala.language.implicitConversions 16 | import scala.reflect._ 17 | 18 | /** 19 | * Extentions to the base fish with extensions done with spring beans. 20 | * @param baseDsl the base fish. 21 | * @tparam I the message body type. 22 | */ 23 | private[camel] class TransformationDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 24 | 25 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 26 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 27 | def bean(str: String): BaseDSL[Any] = bean(str, None) 28 | 29 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 30 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 31 | def bean(str: String, method: String): BaseDSL[Any] = bean(str, Some(method)) 32 | 33 | private[this] def bean(beanRef: String, method: Option[String]): BaseDSL[Any] = { 34 | 35 | TransformerDefinition(BeanNameExpression(beanRef, method)) 36 | } 37 | 38 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 39 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 40 | def bean(ref: AnyRef): BaseDSL[Any] = bean(ref, None) 41 | 42 | private[this] def bean(bean: AnyRef, method: Option[String]): BaseDSL[Any] = { 43 | 44 | TransformerDefinition(BeanObjectExpression(bean, method)) 45 | 46 | } 47 | 48 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 49 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 50 | def bean(ref: AnyRef, method: String): BaseDSL[Any] = bean(ref, Some(method)) 51 | 52 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 53 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 54 | def bean(clazz: Class[_]): BaseDSL[Any] = bean(clazz, None) 55 | 56 | private[this] def bean(clazz: Class[_], method: Option[String]): BaseDSL[Any] = { 57 | 58 | TransformerDefinition(BeanClassExpression(clazz, method)) 59 | 60 | } 61 | 62 | @deprecated("bean keyword is deprecated as it removes type information for the next keyword. " + 63 | "To improve you route typing, please use a process or a processBody with a function.", "version 0.5.0") 64 | def bean(clazz: Class[_], method: String): BaseDSL[Any] = bean(clazz, Some(method)) 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/ValidationDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.ValidationDefinition 12 | import io.xtech.babel.fish._ 13 | import io.xtech.babel.fish.model.{ Message, Predicate } 14 | 15 | import scala.reflect.ClassTag 16 | 17 | private[camel] class ValidationDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 18 | 19 | /** 20 | * The validate defines, using a function, how messages are validated. 21 | * An exception is thrown if the function returns false. 22 | * @param function which defines how a message is validated 23 | * @return the possibility to add other steps to the current DSL 24 | */ 25 | def validate(function: Message[I] => Boolean): BaseDSL[I] = { 26 | ValidationDefinition(MessagePredicate(function)) 27 | } 28 | 29 | /** 30 | * The validate defines, using a predicate (ex: simple language), how messages are validated. 31 | * An exception is thrown if the function returns false. 32 | * @param predicate which defines how a message is validated 33 | * @return the possibility to add other steps to the current DSL 34 | */ 35 | def validate(predicate: Predicate[I]): BaseDSL[I] = { 36 | ValidationDefinition(predicate) 37 | } 38 | 39 | /** 40 | * The validate defines, using a function, how messages are validated. 41 | * An exception is thrown if the function returns false. 42 | * @param function which defines how a message is validated 43 | * @return the possibility to add other steps to the current DSL 44 | */ 45 | def validateBody(function: I => Boolean): BaseDSL[I] = { 46 | ValidationDefinition(BodyPredicate(function)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/WireTapDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.parsing.Wiring 12 | import io.xtech.babel.camel.model.{ CamelMessage, CamelSink, WireTapDefinition } 13 | import io.xtech.babel.fish.model.{ Message, StepDefinition, TransformerDefinition } 14 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL, MessageTransformationExpression } 15 | 16 | import scala.language.implicitConversions 17 | import scala.reflect.ClassTag 18 | 19 | /** 20 | * Adds the wiretap keyword to the BaseDSL. 21 | */ 22 | private[camel] class WireTapDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 23 | 24 | /** 25 | * The wiretap keyword. Defines an endpoint where a copy of exchanges are forwarded, leaving the normal flow of the route. 26 | * @param uri of the endpoint which receives a copy of each exchange 27 | * @return the possibility to add other steps to the current DSL 28 | */ 29 | def wiretap(uri: String): BaseDSL[I] = WireTapDefinition[I](CamelSink[I](uri)) 30 | 31 | /** 32 | * The sideEffect lets you define a route as parameter that do not modify the output of the sideEffect keyword. 33 | * The side route is run sequentially and before the rest of the route. 34 | * @param w route which does not effect the rest of the route. 35 | * @return 36 | */ 37 | def sideEffect(w: (BaseDSL[I]) => BaseDSL[_]): BaseDSL[I] = { 38 | val wireDefinition = new TransformerDefinition(wire) 39 | val dewireDefinition = new TransformerDefinition(dewire) 40 | 41 | baseDsl.step.next = Some(wireDefinition) 42 | val dsl = new BaseDSL[I](wireDefinition) 43 | 44 | w(dsl).step.next = Some(dewireDefinition) 45 | new BaseDSL[I](dewireDefinition) 46 | } 47 | 48 | private def propertyKey(count: Int): String = s"${Wiring.key}-${count + 1}" 49 | private def typeName(implicit ev: ClassTag[I]): String = ev.toString() 50 | 51 | private val wire: MessageTransformationExpression[I, I] = MessageTransformationExpression((msg: Message[I]) => { 52 | val headers = Wiring.getCount(msg) 53 | val wired = HeadersAndBody(msg.headers, msg.body) 54 | msg.asInstanceOf[CamelMessage[I]].withExchangeProperty(propertyKey(headers), wired) //TODO getOrElse 55 | }) 56 | 57 | private val dewire: MessageTransformationExpression[I, I] = MessageTransformationExpression((msg: Message[I]) => { 58 | val key = s"${Wiring.key}-${Wiring.getCount(msg) + 1}" 59 | val wired: HeadersAndBody[I] = msg.asInstanceOf[CamelMessage[_]].exchangeProperties.get(key) match { 60 | case Some(w: HeadersAndBody[I]) => w 61 | case Some(other) => throw new WiredUnexpectedBodyType(typeName, other.getClass.getName) //should never happen 62 | case None => throw new WiredEmptyException() 63 | } 64 | msg.withOptionalBody(_ => wired.body).withHeaders(_ => wired.headers).asInstanceOf[CamelMessage[I]].withExchangeProperties(_ - key) 65 | }) 66 | 67 | } 68 | 69 | class WiringDefinition() extends StepDefinition 70 | 71 | class WiredEmptyException extends IllegalArgumentException("Expected wired message but was empty in Babel sideEffect") 72 | class WiredUnexpectedBodyType(expected: String, actual: String) 73 | extends IllegalArgumentException(s"Body has not expected type in Babel sideEffect: expected $expected, but was $actual") 74 | case class HeadersAndBody[T](headers: Map[String, Any], body: Option[T]) -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/builder/RouteBuilder.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.builder 10 | 11 | import io.xtech.babel.camel._ 12 | import io.xtech.babel.camel.model.EmptyDefinition 13 | import io.xtech.babel.fish.model.RouteDefinition 14 | import io.xtech.babel.fish.{ DSL, NoDSL } 15 | import org.apache.camel.model.ModelCamelContext 16 | import org.apache.camel.{ CamelContext, RoutesBuilder, RuntimeCamelException } 17 | 18 | /** 19 | * Facility trait used to implement RouteBuilder in order to be more integrated into Camel. 20 | * This allows Babel Camel routes to be discovered by the Camel route scanner. 21 | */ 22 | abstract class RouteBuilder extends DSL with CamelDSL with RoutesBuilder { 23 | 24 | //protected val namingStrategy: NamingStrategy = DefaultNamingStrategy 25 | 26 | /** 27 | * stores the RouteBuilder scope configuration 28 | */ 29 | private[this] var handle: Option[EmptyDefinition] = None 30 | 31 | /** 32 | * adds the generated routes to the given Camel Context. 33 | * Used by Spring to populate a Camel Context while scanning the package (though xml configuration) 34 | * @param context to be populated with generated routes 35 | */ 36 | 37 | def addRoutesToCamelContext(context: CamelContext): Unit = context match { 38 | case model: ModelCamelContext => 39 | val definitions = handle.map(new RouteDefinition(_)).toList ::: this.build().toList 40 | val routeBuilder = this.routeBuilder(definitions)(model) 41 | model.addRoutes(routeBuilder) 42 | 43 | case other: CamelContext => throw new RuntimeCamelException("Requires a ModelCamelContext in order to add Babel Fish routes to it.") 44 | } 45 | 46 | /** 47 | * defines a set of rules that are applied on the RouteBuilder itself and not on a route. 48 | * @param block is the rules to be applied to the RouteBuilder 49 | * @return end of DSL: it is not possible to add other keywords to the current DSL. 50 | */ 51 | protected def handle(block: HandlingDSL[Any] => Unit): NoDSL = { 52 | val dsl = new GlobalDSL() 53 | handle match { 54 | case None => 55 | handle = Some(dsl.step) 56 | case Some(h) => 57 | throw new CamelException.ErorrHandlingDefinedTwice 58 | } 59 | new HandlerDSL[Any](dsl).handle(block) 60 | } 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/builder/SpringRouteBuilder.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.builder 10 | 11 | import org.apache.camel.CamelContext 12 | 13 | /** 14 | * The SpringRouteBuilder is helpful to define Babel Camel routes which are dealing with Spring Beans. 15 | * As those beans may not have been initialized, the Babel Camel routes should be define in the body of the configure method. 16 | */ 17 | trait SpringRouteBuilder extends RouteBuilder { 18 | 19 | /** 20 | * The configure method should contain the Babel Camel route definition. 21 | * It ensures the used Spring Beans are initialized before initializing the route definitions. 22 | * Used by the Camel RouteBuilder to load defined Babel Camel routes in the calling Camel Context. 23 | */ 24 | 25 | def configure(): Unit 26 | 27 | override def addRoutesToCamelContext(context: CamelContext): Unit = { 28 | configure() 29 | super.addRoutesToCamelContext(context) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/AggregationStrategy.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import org.apache.camel.Exchange 12 | import org.apache.camel.processor.aggregate.AggregationStrategy 13 | 14 | /** 15 | * An implementation of the fold operation for camel using an Aggregation Strategy 16 | * @param seed the initial value. 17 | * @param fold the fold function 18 | * @tparam I the input type. 19 | * @tparam O the output type. 20 | */ 21 | class FoldBodyAggregationStrategy[I, O](seed: O, fold: (O, I) => O) extends AggregationStrategy { 22 | 23 | def aggregate(oldExchangeParam: Exchange, newExchange: Exchange): Exchange = { 24 | 25 | val oldExchange = Option(oldExchangeParam) 26 | 27 | oldExchange.fold { 28 | 29 | val newBody: I = newExchange.getIn.getBody.asInstanceOf[I] 30 | 31 | val newValue = fold(seed, newBody) 32 | newExchange.getIn.setBody(newValue) 33 | newExchange 34 | }(oldEx => { 35 | 36 | val oldBody: O = oldEx.getIn.getBody.asInstanceOf[O] 37 | val newBody: I = newExchange.getIn.getBody.asInstanceOf[I] 38 | 39 | val v = fold(oldBody, newBody) 40 | oldEx.getIn.setBody(v) 41 | oldEx 42 | }) 43 | } 44 | 45 | } 46 | 47 | /** 48 | * An implementation of the reduce operation for camel using an Aggregation Strategy 49 | * @param reduce the reduce function. 50 | * @tparam I the input type. 51 | */ 52 | class ReduceBodyAggregationStrategy[I](reduce: (I, I) => I) extends AggregationStrategy { 53 | 54 | def aggregate(oldExchangeParam: Exchange, newExchange: Exchange): Exchange = { 55 | 56 | val oldExchange = Option(oldExchangeParam) 57 | 58 | oldExchange.fold(newExchange)(oldEx => { 59 | 60 | val oldBody: I = oldEx.getIn.getBody.asInstanceOf[I] 61 | val newBody: I = newExchange.getIn.getBody.asInstanceOf[I] 62 | 63 | val newValue = reduce(oldBody, newBody) 64 | 65 | oldEx.getIn.setBody(newValue) 66 | 67 | oldEx 68 | }) 69 | } 70 | } 71 | 72 | class EnrichBodyAggregationStrategy[I, O, T](reduce: (I, O) => T) extends AggregationStrategy { 73 | override def aggregate(oldExchangeParam: Exchange, newExchange: Exchange): Exchange = { 74 | val oldExchange = Option(oldExchangeParam) 75 | 76 | oldExchange.fold(newExchange)(oldEx => { 77 | 78 | val oldBody: I = oldEx.getIn.getBody.asInstanceOf[I] 79 | val newBody: O = newExchange.getIn.getBody.asInstanceOf[O] 80 | 81 | val newValue = reduce(oldBody, newBody) 82 | 83 | oldEx.getIn.setBody(newValue) 84 | 85 | oldEx 86 | }) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/CamelSink.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.Sink 12 | 13 | import scala.collection.immutable 14 | 15 | /** 16 | * Sink of a Camel route, implicitly created when calling {{{ to("uri") }}} 17 | * @param uri given to the `to` keyword 18 | */ 19 | case class CamelSink[-I](uri: String) extends Sink[I, Any] 20 | 21 | /** 22 | * An utility object used in matchers to extract a Seq of a CamelSink from a Seq of Sink 23 | * Used in the multicast 24 | */ 25 | protected[camel] object SeqCamelSink { 26 | def unapplySeq(m: immutable.Seq[Sink[_, _]]): Option[Seq[CamelSink[_]]] = { 27 | 28 | val t = m.collect { 29 | case s: CamelSink[_] => s 30 | } 31 | 32 | Some(t) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/CamelSource.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.Source 12 | 13 | /** 14 | * Source of a Camel route, implicitly created when calling {{{ from("uri") }}} 15 | * @param uri given to the `from` keyword 16 | */ 17 | case class CamelSource(uri: String) extends Source[Any] 18 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/EmptyDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ FromDefinition, Source } 12 | 13 | /** 14 | * The EmptySource is used in the EmptyDefinition to specify there is no source to this definition. 15 | * @see io.xtech.babel.camel.model.EmptySource 16 | */ 17 | object EmptySource extends Source[Any] 18 | 19 | /** 20 | * The EmptyDefinition takes place of the FromDefinition as beginning of a Route Definition. Such RouteDefinition are 21 | * defining the error management for the whole RouteBuilder. 22 | */ 23 | class EmptyDefinition extends FromDefinition(classOf[Any], EmptySource) 24 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/EnrichDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Sink, StepDefinition } 12 | import org.apache.camel.processor.aggregate.AggregationStrategy 13 | 14 | /** 15 | * The definition of the enrichRef keyword in the DSL 16 | */ 17 | case class EnrichDefinition[I, O](sink: Sink[I, O], aggregationStrategy: Either[String, AggregationStrategy]) extends StepDefinition 18 | 19 | /** 20 | * The definition of the pollEnrichRef keyword in the DSL 21 | */ 22 | case class PollEnrichDefinition[I, O](sink: Sink[I, O], aggregationStrategy: Either[String, AggregationStrategy], timeout: Long = -1) extends StepDefinition 23 | 24 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/ErrorHandlingRouteDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | 13 | /** 14 | * Declaration of a link to an Error handling Route configuration. 15 | * @param endpoint which connects to the error handling route. 16 | */ 17 | case class ErrorHandlingRouteDefinition(endpoint: String) extends StepDefinition 18 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/LogDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | import org.apache.camel.LoggingLevel 13 | 14 | /** 15 | * Defines the configuration of a log EIP. 16 | * 17 | */ 18 | trait LogProps { 19 | def output: String 20 | } 21 | 22 | /** 23 | * defines a log with its output 24 | */ 25 | case class LogMessage(output: String) extends LogProps 26 | 27 | /** 28 | * defines a log with its logging level and its output 29 | */ 30 | case class LogLoggingLevelMessage(level: LoggingLevel, output: String) extends LogProps 31 | 32 | /** 33 | * defines a log with its logging level, its log name and its output 34 | */ 35 | case class LogLoggingLevelLogNameMessage(level: LoggingLevel, LogName: String, output: String) extends LogProps 36 | 37 | /** 38 | * defines a log with its logging level, its log name, a marker and its output 39 | */ 40 | case class LogLoggingLevelLogNameMarkerMessage(level: LoggingLevel, LogName: String, marker: String, output: String) extends LogProps 41 | 42 | /** 43 | * Defines a Log EIP. 44 | * @param props the logging information. 45 | * @see io.xtech.babel.camel.LogProps 46 | */ 47 | case class LogDefinition(props: LogProps) extends StepDefinition 48 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/MarshallerDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | import org.apache.camel.spi.DataFormat 13 | 14 | /** 15 | * defines a Marshall EIP. 16 | */ 17 | trait MarshallerProps 18 | 19 | case class MarshallerInstance(dataFormat: DataFormat) extends MarshallerProps 20 | 21 | case class MarshallerReference(ref: String) extends MarshallerProps 22 | 23 | case class UnmarshallerInstance(dataFormat: DataFormat) extends MarshallerProps 24 | 25 | case class UnmarshallerReference(ref: String) extends MarshallerProps 26 | 27 | case class MarshallerDefinition(val props: MarshallerProps) extends StepDefinition 28 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/MulticastAggregationDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | package io.xtech.babel.camel.model 9 | 10 | import io.xtech.babel.fish.model.StepDefinition 11 | import org.apache.camel.processor.aggregate.AggregationStrategy 12 | 13 | /** 14 | * The definition of how a multicast aggregates its messages. 15 | * @param aggregation how multicast is aggregating its messages. 16 | * @tparam I the body type of the input message. 17 | */ 18 | case class MulticastAggregationDefinition[I](aggregation: AggregationStrategy) extends StepDefinition -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/Predicate.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Message, Predicate } 12 | import io.xtech.babel.fish.{ BodyPredicate, MessagePredicate } 13 | import org.apache.camel.builder.xml.XPathBuilder 14 | import org.apache.camel.{ Exchange, Predicate => CamelPredicate } 15 | 16 | import scala.util.{ Failure, Success, Try } 17 | 18 | /** 19 | * XPath defines a xpath used for an expression or a predicate. 20 | * @param str 21 | */ 22 | case class XPath(str: String) extends Predicate[Any] 23 | 24 | /** 25 | * Wrapper for a scala function in a Camel Predicate. 26 | * @param predicate a predicate function. 27 | * @tparam I The type of the body message. 28 | */ 29 | class CamelMessagePredicate[I](predicate: (Message[I] => Boolean)) extends CamelPredicate { 30 | 31 | /** 32 | * @see org.apache.camel.Predicate 33 | */ 34 | def matches(exchange: Exchange): Boolean = { 35 | val message = new CamelMessage[I](exchange.getIn) 36 | predicate(message) 37 | } 38 | } 39 | 40 | /** 41 | * Wrapper for a scala function in a Camel Predicate. 42 | * @param predicate a predicate function. 43 | * @tparam I The type of the body message. 44 | */ 45 | class CamelBodyPredicate[I](predicate: (I => Boolean)) extends CamelPredicate { 46 | 47 | /** 48 | * @see org.apache.camel.Predicate 49 | */ 50 | def matches(exchange: Exchange): Boolean = Try { 51 | predicate(exchange.getIn.getBody.asInstanceOf[I]) 52 | } match { 53 | case Success(result) => 54 | result 55 | case Failure(ex) => 56 | ex.printStackTrace() 57 | throw ex 58 | } 59 | 60 | } 61 | 62 | /** 63 | * Wrapper for a Camel Predicate. 64 | * Use to allow the use of Camel Predicate which is implicitly transformed into Babel Predicate. 65 | * @param predicate the real Camel Predicate 66 | */ 67 | case class CamelPredicateWrapper(predicate: org.apache.camel.Predicate) extends Predicate[Any] 68 | 69 | /** 70 | * Facility object that provides a translation from a Babel predicate to a Camel one. 71 | */ 72 | object Predicates { 73 | 74 | def toCamelPredicate[I](predicate: Predicate[I]): CamelPredicate = { 75 | predicate match { 76 | case MessagePredicate(function) => new CamelMessagePredicate(function) 77 | case BodyPredicate(function) => new CamelBodyPredicate(function) 78 | case XPath(xpath) => XPathBuilder.xpath(xpath) 79 | case CamelPredicateWrapper(camelPredicate) => camelPredicate 80 | case _ => throw new Exception(s"unknown type of predicate : $predicate") 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/RecipientListDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Expression, StepDefinition } 12 | 13 | /** 14 | * Defines a RecipientList EIP (Publish and Subscribe) 15 | */ 16 | case class RecipientListDefinition[I, E](expression: Expression[I, E]) extends StepDefinition 17 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/ResequencerDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Expression, StepDefinition } 12 | import org.apache.camel.model.config.ResequencerConfig 13 | 14 | /** 15 | * The definition of a resequencer eip. 16 | * @param expression on what part of the message the comparaison are done. 17 | * @param resequencer the configuration of the resquencer. 18 | * @tparam I the type of the message body. 19 | * @tparam E the type of the message, header, or a piece of the message. 20 | */ 21 | case class ResequencerDefinition[I, E](expression: Expression[I, E], resequencer: ResequencerConfig) extends StepDefinition 22 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/RouteConfigurationDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | import org.apache.camel.Route 13 | import org.apache.camel.spi.RoutePolicy 14 | 15 | /* 16 | * Route configuration model 17 | */ 18 | 19 | case class AutoStartDefinition(noAutoStart: Boolean) extends StepDefinition 20 | 21 | case class OnExchangeBeginDefinition[I](callback: (Route, CamelMessage[I]) => Unit) extends StepDefinition 22 | 23 | case class OnExchangeDoneDefinition[I](callback: (Route, CamelMessage[I]) => Unit) extends StepDefinition 24 | 25 | case class OnStopDefinition(callback: (Route) => Unit) extends StepDefinition 26 | 27 | case class OnResumeDefinition(callback: (Route) => Unit) extends StepDefinition 28 | 29 | case class OnInitDefinition(callback: (Route) => Unit) extends StepDefinition 30 | 31 | case class OnRemoveDefinition(callback: (Route) => Unit) extends StepDefinition 32 | 33 | case class OnStartDefinition(callback: (Route) => Unit) extends StepDefinition 34 | 35 | case class OnSuspendDefinition(callback: (Route) => Unit) extends StepDefinition 36 | 37 | case class RoutePolicyDefinition(policy: Seq[RoutePolicy]) extends StepDefinition 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/RouteIdDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | 13 | /** 14 | * Declaration of an id for a route. 15 | * @param routeId the route id. 16 | */ 17 | case class RouteIdDefinition(val routeId: String) extends StepDefinition 18 | 19 | case class FromIdDefinition(val Id: String) extends StepDefinition 20 | 21 | case class IdDefinition(val Id: String) extends StepDefinition 22 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/SortDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import java.util.Comparator 12 | 13 | import io.xtech.babel.fish.model.{ Expression, StepDefinition } 14 | 15 | /** 16 | * The definition of the sort keyword in the DSL 17 | * @param expression what element of the message is sorted. 18 | * @param comparator how are the element sorted. 19 | * @tparam I input type. 20 | * @tparam O output type. 21 | */ 22 | case class SortDefinition[I, O, C](expression: Expression[I, O], comparator: Option[Comparator[C]]) extends StepDefinition 23 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/ThrottlerDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Expression, StepDefinition } 12 | 13 | /** 14 | * Declaration of a throttler definition 15 | * @param perSecond maximal number of message allowed per second 16 | */ 17 | case class ThrottlerDefinitionLong(perSecond: Long) extends StepDefinition 18 | 19 | /** 20 | * Declaration of a throttler definition 21 | * @param perSecond expression defining maximal number of message allowed per second 22 | */ 23 | case class ThrottlerDefinitionExpression[I](perSecond: Expression[I, Long]) extends StepDefinition 24 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/TransactionDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | 13 | /** 14 | * The definition of a transaction. 15 | * @param ref a reference. 16 | */ 17 | case class TransactionDefinition(ref: Option[String] = None) extends StepDefinition 18 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/ValidationDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Predicate, StepDefinition } 12 | 13 | case class ValidationDefinition[I](expression: Predicate[I]) extends StepDefinition 14 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/model/WireTapDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.model 10 | 11 | import io.xtech.babel.fish.model.{ Sink, StepDefinition } 12 | import org.apache.camel.processor.aggregate.AggregationStrategy 13 | 14 | import scala.collection.immutable 15 | 16 | /** 17 | * Defines a sink where each message is just copied. 18 | */ 19 | case class WireTapDefinition[T](sink: CamelSink[T]) extends StepDefinition 20 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Aggregation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ CamelMessageExpression, Expressions, FoldBodyAggregationStrategy, ReduceBodyAggregationStrategy } 12 | import io.xtech.babel.camel.model.Aggregation._ 13 | import io.xtech.babel.fish.model.AggregationDefinition 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.{ AggregateDefinition, ProcessorDefinition } 16 | 17 | import scala.collection.immutable 18 | 19 | /** 20 | * Defines the parsing of aggregation definitions. 21 | */ 22 | private[babel] trait Aggregation extends CamelParsing { 23 | 24 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 25 | 26 | // parsing of an aggregation definition 27 | private[this] def parse: Process = { 28 | 29 | // parse a native camel aggregation 30 | case StepInformation(AggregationDefinition(CamelAggregation(correlationExpression, aggregationStrategy, completionStrategies)), camelProcessorDefinition: ProcessorDefinition[_]) => { 31 | 32 | val nextProcDef = camelProcessorDefinition.aggregate(Expressions.toCamelExpression(correlationExpression), aggregationStrategy) 33 | 34 | competion(nextProcDef, completionStrategies) 35 | 36 | nextProcDef 37 | } 38 | 39 | case StepInformation(AggregationDefinition(CamelReferenceAggregation(correlationExpression, ref, completionStrategies)), camelProcessorDefinition: ProcessorDefinition[_]) => { 40 | 41 | val nextProcDef = camelProcessorDefinition.aggregate.expression(Expressions.toCamelExpression(correlationExpression)).aggregationStrategyRef(ref) 42 | 43 | competion(nextProcDef, completionStrategies) 44 | 45 | nextProcDef 46 | } 47 | 48 | // parse a reduce definition 49 | case StepInformation(AggregationDefinition(ReduceBody(reduce, groupBy, completionStrategies)), camelProcessorDefinition: ProcessorDefinition[_]) => { 50 | val aggregationStrategy = new ReduceBodyAggregationStrategy(reduce) 51 | 52 | val nextProcDef = camelProcessorDefinition.aggregate(CamelMessageExpression(groupBy), aggregationStrategy) 53 | 54 | competion(nextProcDef, completionStrategies) 55 | 56 | nextProcDef 57 | } 58 | 59 | // parse a fold definition 60 | case StepInformation(AggregationDefinition(FoldBody(seed, fold, groupBy, completionStrategies)), camelProcessorDefinition: ProcessorDefinition[_]) => { 61 | val aggregationStrategy = new FoldBodyAggregationStrategy(seed, fold) 62 | 63 | val nextProcDef = camelProcessorDefinition.aggregate(CamelMessageExpression(groupBy), aggregationStrategy) 64 | 65 | competion(nextProcDef, completionStrategies) 66 | 67 | nextProcDef 68 | } 69 | } 70 | 71 | private[this] def competion(aggregateDefinition: AggregateDefinition, completionStrategies: immutable.Seq[CompletionStrategy]): Unit = { 72 | for (completion <- completionStrategies) { 73 | completion match { 74 | case CompletionInterval(time) => { 75 | aggregateDefinition.setCompletionInterval(time) 76 | } 77 | case CompletionSize(size) => { 78 | aggregateDefinition.setCompletionSize(size) 79 | } 80 | case CompletionTimeout(time) => { 81 | aggregateDefinition.setCompletionTimeout(time) 82 | } 83 | case ForceCompletionOnStop => { 84 | aggregateDefinition.forceCompletionOnStop() 85 | } 86 | case CompletionFromBatchConsumer => { 87 | aggregateDefinition.completionFromBatchConsumer() 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/CamelParsing.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.fish.parsing.Parsing 12 | import org.apache.camel.builder.RouteBuilder 13 | 14 | /** 15 | * The CamelParsing is the parent trait of each keyword parser in babel-camel. 16 | */ 17 | protected[camel] trait CamelParsing extends Parsing[RouteBuilder] 18 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Enricher.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model._ 12 | import io.xtech.babel.camel.{ CamelDSL, EnricherDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.{ EnrichDefinition => CamelEnrichDefinition, PollEnrichDefinition => CamelPollEnrichDefinition, ProcessorDefinition } 16 | import org.apache.camel.processor.aggregate.AggregationStrategy 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | 22 | /** 23 | * Defines the enrich and pollEnrich keyword in the DSL. 24 | */ 25 | private[babel] trait Enricher extends CamelParsing { 26 | self: CamelDSL => 27 | 28 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 29 | 30 | /** 31 | * Parsing of the enricher feature 32 | */ 33 | private[this] def parse: Process = { 34 | 35 | // parsing of the enrichRef keyword 36 | case StepInformation(step @ EnrichDefinition(CamelSink(resourceUri), aggregationRef), camelProcessorDefinition: ProcessorDefinition[_]) => { 37 | 38 | val camelEnrichDefinition = aggregationRef match { 39 | case Left(ref) => 40 | val definition = new CamelEnrichDefinition(resourceUri) 41 | definition.setAggregationStrategyRef(ref) 42 | definition 43 | case Right(strategy) => 44 | new CamelEnrichDefinition(strategy, resourceUri) 45 | } 46 | 47 | camelProcessorDefinition.addOutput(camelEnrichDefinition) 48 | camelProcessorDefinition.withId(step) 49 | 50 | } 51 | 52 | // parsing of the pollEnrich keyword 53 | case StepInformation(step @ PollEnrichDefinition(CamelSink(resourceUri), aggregationRef, timeout), camelProcessorDefinition: ProcessorDefinition[_]) => { 54 | 55 | val camelPollEnrichDefinition = aggregationRef match { 56 | case Left(ref) => 57 | val definition = new CamelPollEnrichDefinition() 58 | definition.setResourceUri(resourceUri) 59 | definition.setAggregationStrategyRef(ref) 60 | definition.setTimeout(timeout) 61 | definition 62 | case Right(strategy) => 63 | new CamelPollEnrichDefinition(strategy, resourceUri, timeout) 64 | } 65 | 66 | camelProcessorDefinition.addOutput(camelPollEnrichDefinition) 67 | camelProcessorDefinition.withId(step) 68 | } 69 | } 70 | 71 | protected implicit def enrichDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new EnricherDSL(baseDsl) 72 | 73 | } 74 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Handler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ ErrorHandling, ErrorHandlingRouteDefinition, OnExceptionDefinition } 12 | import io.xtech.babel.camel.{ CamelDSL, HandlerDSL } 13 | import io.xtech.babel.fish.parsing.StepInformation 14 | import io.xtech.babel.fish.{ BodyPredicate, FromDSL } 15 | import org.apache.camel.builder.RouteBuilder 16 | import org.apache.camel.model.ProcessorDefinition 17 | 18 | import scala.collection.JavaConverters._ 19 | import scala.collection.immutable 20 | import scala.language.implicitConversions 21 | import scala.reflect.ClassTag 22 | 23 | /** 24 | * The Exception Handler parser. 25 | */ 26 | private[babel] trait Handler extends CamelParsing { 27 | self: CamelDSL => 28 | 29 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 30 | 31 | /** 32 | * parses the error handling keyword, at both level : Route and RouteBuilder 33 | */ 34 | private[this] def parse: Process = { 35 | 36 | //handling at Route level 37 | case s @ StepInformation(exception: OnExceptionDefinition[_], camelProcessorDefinition: ProcessorDefinition[_]) => 38 | parseOnException(exception, camelProcessorDefinition.onException(exception.exception)) 39 | s.buildHelper //if sub exists for this onException, it should be parsed specifically... 40 | 41 | case s @ StepInformation(handler: ErrorHandling, camelProcessorDefinition: ProcessorDefinition[_]) => 42 | s.buildHelper.getRouteCollection.getRoutes.asScala.lastOption.map(_.setErrorHandlerBuilder(handler.camelErrorHandlerBuilder)) 43 | camelProcessorDefinition 44 | 45 | //handling at RouteBuilder level 46 | case s @ StepInformation(exception: OnExceptionDefinition[_], _: RouteBuilder) => 47 | val camelProcessor = s.buildHelper.onException(exception.exception) 48 | parseOnException(exception, camelProcessor) 49 | (camelProcessor, s.buildHelper) 50 | 51 | case s @ StepInformation(handler: ErrorHandling, _: RouteBuilder) => 52 | s.buildHelper.errorHandler(handler.camelErrorHandlerBuilder) 53 | s.buildHelper 54 | 55 | case step @ StepInformation(d: ErrorHandlingRouteDefinition, camelProcessor) => { 56 | //is parsed by the previous step, @see parseOnException 57 | } 58 | 59 | } 60 | 61 | private[this] def parseOnException[T <: Throwable, I](exception: OnExceptionDefinition[T], processor: org.apache.camel.model.OnExceptionDefinition): Unit = { 62 | //Warning: predicates and functions here may cause Camel to fail silently (without printing any exception) 63 | 64 | exception.applyToCamel(processor) 65 | 66 | //parse the handlingRoute if any 67 | exception.next.foreach { 68 | case channel: ErrorHandlingRouteDefinition => 69 | val to = processor.to(channel.endpoint) 70 | namingStrategy.name(channel).foreach(to.id) 71 | to 72 | } 73 | processor.end() 74 | } 75 | 76 | protected implicit def handlerDSLExtension[I: ClassTag](baseDsl: FromDSL[I]): HandlerDSL[I] = new HandlerDSL(baseDsl) 77 | 78 | //used to allow user to define a predicate on exceptions from a boolean 79 | protected implicit def booleanAsPredicate[Any](bool: Boolean): BodyPredicate[Any] = { 80 | BodyPredicate[Any](_ => bool) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Log.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model._ 12 | import io.xtech.babel.camel.{ CamelDSL, LogDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.collection.immutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | /** 22 | * The log parser. 23 | */ 24 | private[babel] trait Log extends CamelParsing { 25 | self: CamelDSL => 26 | 27 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 28 | 29 | private[this] def parse: Process = { 30 | 31 | case StepInformation(step @ LogDefinition(LogMessage(message)), camelProcessorDefinition: ProcessorDefinition[_]) => { 32 | camelProcessorDefinition.log(message).withId(step) 33 | } 34 | 35 | case StepInformation(step @ LogDefinition(LogLoggingLevelMessage(level, message)), camelProcessorDefinition: ProcessorDefinition[_]) => { 36 | camelProcessorDefinition.log(level, message).withId(step) 37 | } 38 | 39 | case StepInformation(step @ LogDefinition(LogLoggingLevelLogNameMessage(level, name, message)), camelProcessorDefinition: ProcessorDefinition[_]) => { 40 | camelProcessorDefinition.log(level, name, message).withId(step) 41 | } 42 | 43 | case StepInformation(step @ LogDefinition(LogLoggingLevelLogNameMarkerMessage(level, name, marker, message)), camelProcessorDefinition: ProcessorDefinition[_]) => { 44 | camelProcessorDefinition.log(level, name, marker, message).withId(step) 45 | } 46 | } 47 | 48 | protected implicit def logDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): LogDSL[I] = new LogDSL(baseDsl) 49 | } 50 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Marshaller.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model._ 12 | import io.xtech.babel.camel.{ CamelDSL, MarshallerDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.collection.immutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | /** 22 | * The `marshall` / `unmarshall` parser 23 | */ 24 | private[babel] trait Marshaller extends CamelParsing { 25 | self: CamelDSL => 26 | 27 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 28 | 29 | /** 30 | * Parsing of the marshalling feature 31 | */ 32 | private[this] def parse: Process = { 33 | case StepInformation(step @ MarshallerDefinition(MarshallerInstance(dataFormat)), camelProcessorDefinition: ProcessorDefinition[_]) => { 34 | camelProcessorDefinition.marshal(dataFormat).withId(step) 35 | 36 | } 37 | case StepInformation(step @ MarshallerDefinition(MarshallerReference(ref)), camelProcessorDefinition: ProcessorDefinition[_]) => { 38 | camelProcessorDefinition.marshal(ref).withId(step) 39 | 40 | } 41 | case StepInformation(step @ MarshallerDefinition(UnmarshallerInstance(dataFormat)), camelProcessorDefinition: ProcessorDefinition[_]) => { 42 | camelProcessorDefinition.unmarshal(dataFormat).withId(step) 43 | 44 | } 45 | case StepInformation(step @ MarshallerDefinition(UnmarshallerReference(ref)), camelProcessorDefinition: ProcessorDefinition[_]) => { 46 | camelProcessorDefinition.unmarshal(ref).withId(step) 47 | 48 | } 49 | } 50 | 51 | protected implicit def marshallerDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new MarshallerDSL(baseDsl) 52 | } 53 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/RecipientList.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ Expressions, RecipientListDefinition } 12 | import io.xtech.babel.camel.{ CamelDSL, RecipientListDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.model.StepDefinition 15 | import io.xtech.babel.fish.parsing.StepInformation 16 | import org.apache.camel.model.ProcessorDefinition 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | 22 | /** 23 | * The recipientList parser. 24 | */ 25 | private[babel] trait RecipientList extends CamelParsing { 26 | self: CamelDSL => 27 | 28 | // insert the extension in the base fish 29 | protected implicit def recipientListDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new RecipientListDSL(baseDsl) 30 | 31 | // add the recipientList parser to the other parsers 32 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 33 | 34 | private[this] def parse: Process = { 35 | case StepInformation(definition @ RecipientListDefinition(expression), camelProcessorDefinition: ProcessorDefinition[_]) => { 36 | 37 | camelProcessorDefinition.recipientList(Expressions.toCamelExpression(expression)).withId(definition) 38 | 39 | } 40 | } 41 | } 42 | 43 | class RecipientlistDSL[I: ClassTag](step: StepDefinition) extends BaseDSL[I](step) 44 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Resequencer.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ Expressions, ResequencerDefinition } 12 | import io.xtech.babel.camel.{ CamelDSL, ResequencerDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | import org.apache.camel.model.config.{ BatchResequencerConfig, StreamResequencerConfig } 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | 22 | /** 23 | * The parser of resequencer definition. 24 | */ 25 | private[babel] trait Resequencer extends CamelParsing { 26 | self: CamelDSL => 27 | 28 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 29 | 30 | private[this] def parse: Process = { 31 | 32 | case StepInformation(step @ ResequencerDefinition(expression, batch: BatchResequencerConfig), camelProcessorDefinition: ProcessorDefinition[_]) => { 33 | 34 | camelProcessorDefinition.resequence(Expressions.toCamelExpression(expression)).batch(batch).withId(step) 35 | 36 | } 37 | case StepInformation(step @ ResequencerDefinition(expression, stream: StreamResequencerConfig), camelProcessorDefinition: ProcessorDefinition[_]) => { 38 | 39 | camelProcessorDefinition.resequence(Expressions.toCamelExpression(expression)).stream(stream).withId(step) 40 | 41 | } 42 | } 43 | 44 | protected implicit def resequencerDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): ResequencerDSL[I] = new ResequencerDSL(baseDsl) 45 | } 46 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/RouteId.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model._ 12 | import io.xtech.babel.camel.{ CamelDSL, IdDSL, RouteIdDSL } 13 | import io.xtech.babel.fish.model.FromDefinition 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import io.xtech.babel.fish.{ BaseDSL, FromDSL } 16 | import org.apache.camel.model.{ ProcessorDefinition, RouteDefinition } 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | import scala.util.Try 22 | 23 | /** 24 | * The routeId parser. 25 | */ 26 | private[babel] trait RouteId extends CamelParsing { 27 | self: CamelDSL => 28 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 29 | 30 | private[this] def parse: Process = { 31 | 32 | case s @ StepInformation(RouteIdDefinition(routeId), camelProcessorDefinition: ProcessorDefinition[_]) => { 33 | 34 | //renames the from id 35 | s.previousStepHelper match { 36 | case from: RouteDefinition => 37 | Try { 38 | namingStrategy.newRoute() 39 | namingStrategy.routeId = Some(routeId) 40 | namingStrategy.name(FromDefinition(classOf[Any], from.getInputs.get(0).getUri())).foreach(from.id(_)) 41 | } 42 | case other: Any => 43 | namingStrategy.routeId = Some(routeId) 44 | } 45 | camelProcessorDefinition.routeId(routeId) 46 | 47 | } 48 | 49 | case StepInformation(IdDefinition(id), camelProcessorDefinition: ProcessorDefinition[_]) => { 50 | 51 | camelProcessorDefinition.id(id) 52 | 53 | } 54 | 55 | } 56 | 57 | implicit protected def routeIdDSLExtension[I: ClassTag](baseDsl: FromDSL[I]): RouteIdDSL[I] = new RouteIdDSL(baseDsl) 58 | 59 | implicit protected def idDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): IdDSL[I] = new IdDSL(baseDsl) 60 | } 61 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Sort.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ Expressions, SortDefinition } 12 | import io.xtech.babel.camel.{ CamelDSL, SortDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.collection.immutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | /** 22 | * The sort parser. 23 | */ 24 | private[babel] trait Sort extends CamelParsing { 25 | self: CamelDSL => 26 | 27 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 28 | 29 | private[this] def parse: Process = { 30 | 31 | case StepInformation(step @ SortDefinition(expression, Some(comparator)), camelProcessorDefinition: ProcessorDefinition[_]) => { 32 | 33 | camelProcessorDefinition.sort(Expressions.toJavaListCamelExpression(expression), comparator).withId(step) 34 | 35 | } 36 | 37 | case StepInformation(step @ SortDefinition(expression, None), camelProcessorDefinition: ProcessorDefinition[_]) => { 38 | 39 | camelProcessorDefinition.sort(Expressions.toJavaListCamelExpression(expression)).withId(step) 40 | 41 | } 42 | } 43 | 44 | implicit protected def sortDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): SortDSL[I] = new SortDSL(baseDsl) 45 | } 46 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Throttler.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ Expressions, ThrottlerDefinitionExpression, ThrottlerDefinitionLong } 12 | import io.xtech.babel.camel.{ CamelDSL, ThrottlerDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.reflect.ClassTag 18 | 19 | /** 20 | * Defines the parsing of the throttle keyword. 21 | */ 22 | trait Throttler extends CamelParsing { 23 | self: CamelDSL => 24 | 25 | private val parse: Process = { 26 | case StepInformation(step @ ThrottlerDefinitionLong(perSecond), camelProcessor: ProcessorDefinition[_]) => 27 | camelProcessor.throttle(perSecond).withId(step) 28 | 29 | case StepInformation(step @ ThrottlerDefinitionExpression(perSecond), camelProcessor: ProcessorDefinition[_]) => 30 | camelProcessor.throttle(Expressions.toCamelExpression(perSecond)).withId(step) 31 | 32 | } 33 | 34 | abstract override protected def steps = super.steps :+ parse 35 | 36 | protected implicit def throttlerDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new ThrottlerDSL(baseDsl) 37 | } 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Transaction.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.TransactionDefinition 12 | import io.xtech.babel.camel.{ CamelDSL, TransactionDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.collection.immutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | /** 22 | * Defines a transaction in the CamelDSL. 23 | */ 24 | private[babel] trait Transaction extends CamelParsing { 25 | self: CamelDSL => 26 | 27 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 28 | 29 | // parsing of an transaction definition 30 | private[this] def parse: Process = { 31 | 32 | case StepInformation(step @ TransactionDefinition(ref), camelProcessorDefinition: ProcessorDefinition[_]) => { 33 | 34 | val nextCamelProcessor = ref.fold(camelProcessorDefinition.transacted())(ref => camelProcessorDefinition.transacted(ref)) 35 | nextCamelProcessor.withId(step) 36 | 37 | } 38 | 39 | } 40 | 41 | protected implicit def transactedDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): TransactionDSL[I] = new TransactionDSL(baseDsl) 42 | } 43 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Transformation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ BeanClassExpression, BeanNameExpression, BeanObjectExpression } 12 | import io.xtech.babel.camel.{ CamelDSL, TransformationDSL } 13 | import io.xtech.babel.fish.model.{ Message, TransformerDefinition } 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import io.xtech.babel.fish.{ BaseDSL, BodyExpression, MessageTransformationExpression } 16 | import org.apache.camel.model.ProcessorDefinition 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | 22 | /** 23 | * Parser for the transformation definitions 24 | */ 25 | private[babel] trait Transformation extends CamelParsing { 26 | self: CamelDSL => 27 | 28 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 29 | 30 | /** 31 | * Parses the "processBody" statement. 32 | * @see CamelDSL.StepImplementation 33 | */ 34 | private[this] def parse: Process = { 35 | 36 | case StepInformation(step @ TransformerDefinition(BodyExpression(function)), camelProcessorDefinition: ProcessorDefinition[_]) => { 37 | 38 | camelProcessorDefinition.process(bodyFunctionToProcess(function)) 39 | camelProcessorDefinition.withId(step) 40 | } 41 | 42 | case StepInformation(step @ TransformerDefinition(MessageTransformationExpression(function)), camelProcessorDefinition: ProcessorDefinition[_]) => { 43 | 44 | camelProcessorDefinition.process(messageFunctionToProcess(function)) 45 | camelProcessorDefinition.withId(step) 46 | } 47 | 48 | case StepInformation(step @ TransformerDefinition(BeanNameExpression(beanRef, method)), camelProcessorDefinition: ProcessorDefinition[_]) => { 49 | 50 | method.fold(camelProcessorDefinition.beanRef(beanRef))(methodName => camelProcessorDefinition.beanRef(beanRef, methodName)).withId(step) 51 | 52 | } 53 | 54 | // use an instance of a bean as a transformer 55 | case StepInformation(step @ TransformerDefinition(BeanObjectExpression(obj, method)), camelProcessorDefinition: ProcessorDefinition[_]) => { 56 | 57 | method.fold(camelProcessorDefinition.bean(obj))(m => camelProcessorDefinition.bean(obj, m)).withId(step) 58 | } 59 | 60 | // create a transformer from a class description 61 | case StepInformation(step @ TransformerDefinition(BeanClassExpression(clazz, method)), camelProcessorDefinition: ProcessorDefinition[_]) => { 62 | 63 | method.fold(camelProcessorDefinition.bean(clazz))(m => camelProcessorDefinition.bean(clazz, m)).withId(step) 64 | } 65 | } 66 | 67 | private[this] def bodyFunctionToProcess[I, O](function: (I => O)): org.apache.camel.Processor = new CamelBodyProcessor(function) 68 | 69 | private[this] def messageFunctionToProcess[I, O](function: (Message[I] => Message[O])): org.apache.camel.Processor = new CamelMessageProcessor(function) 70 | 71 | protected implicit def transformationDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): TransformationDSL[I] = new TransformationDSL(baseDsl) 72 | } 73 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Validation.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.{ Predicates, ValidationDefinition } 12 | import io.xtech.babel.camel.{ CamelDSL, ValidationDSL } 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.parsing.StepInformation 15 | import org.apache.camel.model.ProcessorDefinition 16 | 17 | import scala.collection.immutable 18 | import scala.language.implicitConversions 19 | import scala.reflect.ClassTag 20 | 21 | private[babel] trait Validation extends CamelParsing { 22 | self: CamelDSL => 23 | 24 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 25 | 26 | // parsing of an validation definition 27 | private[this] def parse: Process = { 28 | 29 | case StepInformation(step @ ValidationDefinition(expression), camelProcessorDefinition: ProcessorDefinition[_]) => { 30 | camelProcessorDefinition.validate(Predicates.toCamelPredicate(expression)).withId(step) 31 | } 32 | } 33 | 34 | protected implicit def validationDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new ValidationDSL(baseDsl) 35 | } 36 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/WireTap.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.{ CamelDSL, WireTapDSL } 12 | import io.xtech.babel.camel.model.WireTapDefinition 13 | import io.xtech.babel.fish.BaseDSL 14 | import io.xtech.babel.fish.model.Message 15 | import io.xtech.babel.fish.parsing.StepInformation 16 | import org.apache.camel.model.ProcessorDefinition 17 | 18 | import scala.collection.immutable 19 | import scala.language.implicitConversions 20 | import scala.reflect.ClassTag 21 | 22 | /** 23 | * The wiretap parser. 24 | */ 25 | private[babel] trait WireTap extends CamelParsing { 26 | self: CamelDSL => 27 | 28 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 29 | 30 | private[this] def parse: Process = { 31 | 32 | case StepInformation(step @ WireTapDefinition(sink), camelProcessorDefinition: ProcessorDefinition[_]) => { 33 | 34 | camelProcessorDefinition.wireTap(sink.uri).withId(step) 35 | 36 | } 37 | 38 | } 39 | 40 | protected implicit def wiretapDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]) = new WireTapDSL(baseDsl) 41 | } 42 | 43 | object Wiring { 44 | val key: String = "babel-wiring-body" 45 | 46 | def getCount(msg: Message[_]): Int = { 47 | msg.headers.keys.count(_.startsWith(Wiring.key)) 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/main/scala/io/xtech/babel/camel/parsing/Wrapper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.parsing 10 | 11 | import io.xtech.babel.camel.model.CamelMessage 12 | import io.xtech.babel.fish.model.Message 13 | import org.apache.camel.{ Exchange, InvalidPayloadException, Processor } 14 | 15 | /** 16 | * Wrapper for a scala function in a Camel Processor. 17 | * The function is used to process message bodies. 18 | * @param proc the function that process body messages. 19 | * @tparam I the input type of the function. 20 | * @tparam O the output type of the function. 21 | */ 22 | private[camel] class CamelBodyProcessor[I, O](proc: (I => O)) extends Processor { 23 | def process(exchange: Exchange): Unit = { 24 | 25 | val newBody = proc(exchange.getIn.getBody.asInstanceOf[I]) 26 | exchange.getIn.setBody(newBody) 27 | } 28 | } 29 | 30 | /** 31 | * Wrapper for a scala function in a Camel Processor. 32 | * The function is used to process messages. 33 | * @param proc the function that process messages. 34 | * @tparam I the input type of the function. 35 | * @tparam O the output type of the function. 36 | */ 37 | private[camel] class CamelMessageProcessor[I, O](proc: (Message[I] => Message[O])) extends Processor { 38 | def process(exchange: Exchange): Unit = { 39 | 40 | val msg = new CamelMessage[I](exchange.getIn) 41 | proc(msg) 42 | } 43 | } 44 | 45 | private[camel] object CamelBodyTypeValidation { 46 | 47 | /** 48 | * Mapping between primitive types and wrapped types. 49 | * Used in order to accept, in requireAs, corresponding Scala types. 50 | */ 51 | val primitiveToBoxed = Map[Class[_], Class[_]]( 52 | classOf[Byte] -> classOf[java.lang.Byte], 53 | classOf[Short] -> classOf[java.lang.Short], 54 | classOf[Char] -> classOf[java.lang.Character], 55 | classOf[Int] -> classOf[java.lang.Integer], 56 | classOf[Long] -> classOf[java.lang.Long], 57 | classOf[Float] -> classOf[java.lang.Float], 58 | classOf[Double] -> classOf[java.lang.Double], 59 | classOf[Boolean] -> classOf[java.lang.Boolean], 60 | classOf[Unit] -> classOf[java.lang.Void] 61 | ).withDefault(identity) 62 | } 63 | 64 | /** 65 | * Processor that checks the validity of the body type 66 | * @param outputClass the required type. 67 | * @tparam O the required type 68 | */ 69 | private[camel] class CamelBodyTypeValidation[O](outputClass: Class[O]) extends Processor { 70 | 71 | def process(exchange: Exchange): Unit = { 72 | 73 | exchange.getIn.getMandatoryBody match { 74 | case c: Any if outputClass.isPrimitive & CamelBodyTypeValidation.primitiveToBoxed(outputClass).isAssignableFrom(c.getClass) => 75 | case c: Any if outputClass.isAssignableFrom(c.getClass) => 76 | case _ => throw new InvalidPayloadException(exchange, outputClass) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/java/io/xtech/babel/camel/javaprocessors/JavaProcessors.java: -------------------------------------------------------------------------------- 1 | package io.xtech.babel.camel.javaprocessors; 2 | 3 | import io.xtech.babel.fish.JVMFunction; 4 | import io.xtech.babel.fish.JVMPredicate; 5 | 6 | /** 7 | * Created by babel on 8/24/15. 8 | */ 9 | public class JavaProcessors { 10 | public static final JVMFunction append = new JVMFunction() { 11 | public String apply(String input) { 12 | return input + "-"; 13 | } 14 | }; 15 | 16 | public static final JVMPredicate containsTrue = new JVMPredicate() { 17 | public boolean apply(String input) { 18 | return input.contains("true"); 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/resources/META-INF/spring/context-constructor-injection.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/resources/META-INF/spring/context-setter-injection.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/resources/META-INF/spring/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 19 | 20 | io.xtech.babel.camel.builder.spring 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | # All rights reserved. 5 | # 6 | # ================================================================================== 7 | # 8 | 9 | # 10 | # The logging properties used for eclipse testing, We want to see debug output on the console. 11 | # 12 | log4j.rootLogger=INFO, out 13 | 14 | # uncomment the following line to turn on Camel debugging 15 | #log4j.logger.org.apache.camel=DEBUG 16 | 17 | # uncomment the following line to turn on ActiveMQ debugging 18 | #log4j.logger.org.apache.activemq=DEBUG 19 | 20 | log4j.logger.org.springframework=ERROR 21 | 22 | 23 | # CONSOLE appender not used by default 24 | log4j.appender.out=org.apache.log4j.ConsoleAppender 25 | log4j.appender.out.layout=org.apache.log4j.PatternLayout 26 | log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n 27 | #log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n 28 | 29 | 30 | log4j.logger.my.cool.toto=TRACE, Appender 31 | log4j.appender.Appender=io.xtech.babel.camel.Appender 32 | 33 | log4j.logger.my.cool.tata=TRACE, ErrorAppender 34 | log4j.appender.ErrorAppender=io.xtech.babel.camel.ErrorAppender 35 | 36 | log4j.logger.my.cool.titi=TRACE, RBErrorAppender 37 | log4j.appender.RBErrorAppender=io.xtech.babel.camel.RBErrorAppender 38 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE USERS(name varchar(256)); 2 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/CompilationSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.model.Aggregation.{ CompletionSize, ReduceBody } 12 | import io.xtech.babel.fish.model.Message 13 | import org.specs2.mutable.Specification 14 | 15 | class CompilationSpec extends Specification { 16 | 17 | "The Scala compiler" should { 18 | 19 | "compile this CamelDSL route" in { 20 | 21 | import io.xtech.babel.camel.builder.RouteBuilder 22 | 23 | val reduceBody = ReduceBody((a: Int, b: Int) => a + b, (msg: Message[Int]) => "a", completionStrategies = List(CompletionSize(3))) 24 | 25 | new RouteBuilder { 26 | from("direct:input").as[Int].aggregate(reduceBody).marshal("id").bean("id").to("direct:output") 27 | } 28 | 29 | success 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/LogSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.test.camel 12 | import org.apache.camel.component.mock.MockEndpoint 13 | import org.apache.log4j._ 14 | import org.apache.log4j.spi.LoggingEvent 15 | import org.specs2.mutable.SpecificationWithJUnit 16 | 17 | import scala.collection.immutable 18 | 19 | class LogSpec extends SpecificationWithJUnit { 20 | sequential 21 | 22 | "A log" should { 23 | 24 | "ouput correctly" in new camel { 25 | 26 | //#doc:babel-camel-logging 27 | 28 | import io.xtech.babel.camel.builder.RouteBuilder 29 | import org.apache.camel.LoggingLevel 30 | 31 | val routeBuilder = new RouteBuilder { 32 | from("direct:input") 33 | //logs to the Trace level message such as "received ID-3423 -> toto" 34 | .log(LoggingLevel.TRACE, "my.cool.toto", "foo", "received: ${id} -> ${body}") 35 | //logs to the Info level message such as "ID-3423 -> toto" 36 | .log(LoggingLevel.INFO, "${id} -> ${body}") 37 | .to("mock:output") 38 | } 39 | //#doc:babel-camel-logging 40 | 41 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 42 | 43 | mock.expectedBodiesReceived("babel message") 44 | 45 | camelContext.addRoutes(routeBuilder) 46 | 47 | camelContext.start() 48 | 49 | val template = camelContext.createProducerTemplate() 50 | template.sendBody("direct:input", "babel message") 51 | mock.assertIsSatisfied() must not(throwA[Exception]) 52 | 53 | SharedLogs.events.size must be_==(1).eventually 54 | 55 | val event = SharedLogs.events.head 56 | event.getLevel === Level.TRACE 57 | event.getLoggerName === "my.cool.toto" 58 | event.getMessage.toString.startsWith("received") must beTrue 59 | event.getMessage.toString.endsWith("babel message") must beTrue 60 | 61 | } 62 | 63 | "be used with a function" in new camel { 64 | 65 | SharedLogs.events = List.empty[LoggingEvent] 66 | 67 | import io.xtech.babel.camel.builder.RouteBuilder 68 | import org.apache.camel.LoggingLevel 69 | 70 | //#doc:babel-camel-logging-functionnal 71 | val routeBuilder = new RouteBuilder { 72 | from("direct:input") 73 | .log(LoggingLevel.TRACE, "my.cool.toto", "foo", msg => "FOO") 74 | .log(msg => s"BAR : ${msg.headers}") 75 | .to("mock:output") 76 | } 77 | //#doc:babel-camel-logging-functionnal 78 | 79 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 80 | 81 | mock.expectedBodiesReceived("babel message") 82 | 83 | camelContext.addRoutes(routeBuilder) 84 | 85 | camelContext.start() 86 | 87 | val template = camelContext.createProducerTemplate() 88 | template.sendBody("direct:input", "babel message") 89 | mock.assertIsSatisfied() must not(throwA[Exception]) 90 | 91 | SharedLogs.events.size must be_==(1).eventually 92 | 93 | val event = SharedLogs.events.head 94 | event.getLevel === Level.TRACE 95 | event.getLoggerName === "my.cool.toto" 96 | event.getMessage.toString must be_==("FOO") 97 | 98 | } 99 | 100 | } 101 | 102 | } 103 | 104 | object SharedLogs { 105 | var events: immutable.Seq[LoggingEvent] = List.empty[LoggingEvent] 106 | } 107 | 108 | class Appender extends AppenderSkeleton { 109 | 110 | def append(event: LoggingEvent): Unit = { 111 | SharedLogs.events :+= event 112 | } 113 | 114 | def close(): Unit = {} 115 | 116 | def requiresLayout(): Boolean = false 117 | } 118 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/MockSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.builder.RouteBuilder 12 | import org.apache.camel.impl.DefaultCamelContext 13 | import org.specs2.mutable.SpecificationWithJUnit 14 | 15 | class MockSpec extends SpecificationWithJUnit { 16 | sequential 17 | 18 | "extend the DSL with some sub DSL (mock)" in { 19 | 20 | val camelContext = new DefaultCamelContext() 21 | 22 | //#doc:babel-camel-mock 23 | import io.xtech.babel.camel.mock._ 24 | 25 | //The Mock extension is added simply by 26 | // extending the RouteBuilder with 27 | val routeDef = new RouteBuilder with Mock { 28 | //the mock keyword is the same as typing 29 | // to("mock:output1") 30 | from("direct:input"). 31 | requireAs[String]. 32 | mock("output1"). 33 | //the mock keyword keeps the same body type (here: String) 34 | processBody(x => x.toUpperCase). 35 | mock("output2") 36 | 37 | } 38 | 39 | //#doc:babel-camel-mock 40 | 41 | routeDef.addRoutesToCamelContext(camelContext) 42 | 43 | camelContext.start() 44 | 45 | val mockEndpoint1 = camelContext.mockEndpoint("output1") 46 | val mockEndpoint2 = camelContext.getMockEndpoint("output2") 47 | 48 | mockEndpoint1.expectedBodiesReceived("test") 49 | mockEndpoint2.expectedBodiesReceived("TEST") 50 | 51 | val producer = camelContext.createProducerTemplate() 52 | 53 | producer.sendBody("direct:input", "test") 54 | 55 | mockEndpoint1.assertIsSatisfied() 56 | mockEndpoint2.assertIsSatisfied() 57 | 58 | camelContext.shutdown() must not(throwA[Exception]) 59 | 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/RouteIdSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.test.camel 12 | import org.specs2.mutable.SpecificationWithJUnit 13 | 14 | class RouteIdSpec extends SpecificationWithJUnit { 15 | sequential 16 | 17 | "A route id" should { 18 | 19 | "be set in a route" in new camel { 20 | 21 | import io.xtech.babel.camel.builder.RouteBuilder 22 | 23 | //#doc:babel-camel-routeId 24 | 25 | val routeBuilder = new RouteBuilder { 26 | from("direct:input"). 27 | //the routeId of this route will be "bla" 28 | routeId("bla"). 29 | //the routeId keyword needs to be at the beginning of the route 30 | // (enforced by the Babel DSL) 31 | to("mock:output") 32 | } 33 | //#doc:babel-camel-routeId 34 | 35 | camelContext.addRoutes(routeBuilder) 36 | 37 | camelContext.start() 38 | 39 | Option(camelContext.getRouteDefinition("bla")) must beSome 40 | } 41 | 42 | "not be empty" in new camel { 43 | 44 | import io.xtech.babel.camel.builder.RouteBuilder 45 | 46 | //#doc:babel-camel-routeId-exception-1 47 | val route = new RouteBuilder { 48 | from("direct:input"). 49 | //a routeId may not be empty 50 | routeId("") must throwA[IllegalArgumentException] 51 | } 52 | //#doc:babel-camel-routeId-exception-1 53 | } 54 | 55 | "not be null" in new camel { 56 | 57 | import io.xtech.babel.camel.builder.RouteBuilder 58 | 59 | //#doc:babel-camel-routeId-exception-2 60 | 61 | val route = new RouteBuilder { 62 | from("direct:input"). 63 | //a routeId may not be null 64 | routeId(null) must throwA[IllegalArgumentException] 65 | } 66 | 67 | //#doc:babel-camel-routeId-exception-2 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/ThrottlerSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.builder.RouteBuilder 12 | import io.xtech.babel.camel.mock._ 13 | import io.xtech.babel.camel.test.camel 14 | import org.apache.camel.builder.{ RouteBuilder => CRouteBuilder } 15 | import org.apache.camel.component.mock.MockEndpoint 16 | import org.specs2.mutable.SpecificationWithJUnit 17 | 18 | class ThrottlerSpec extends SpecificationWithJUnit { 19 | sequential 20 | 21 | "throttle message flow" in new camel { 22 | 23 | val msgs = 3 24 | 25 | //#doc:babel-camel-throttler 26 | 27 | val routeDef = new RouteBuilder { 28 | from("direct:input"). 29 | //throttle message to 1 per second 30 | throttle(1). 31 | to("mock:output") 32 | } 33 | //#doc:babel-camel-throttler 34 | 35 | val nativeRoute = new CRouteBuilder() { 36 | def configure(): Unit = { 37 | from("direct:inputCamel"). 38 | throttle(1). 39 | to("mock:output") 40 | } 41 | } 42 | 43 | routeDef.addRoutesToCamelContext(camelContext) 44 | camelContext.addRoutes(nativeRoute) 45 | 46 | camelContext.start() 47 | 48 | val mockEndpoint = camelContext.mockEndpoint("output") 49 | 50 | mockEndpoint.setExpectedMessageCount(msgs) 51 | 52 | val producer = camelContext.createProducerTemplate() 53 | 54 | val initTime = System.currentTimeMillis() 55 | (1 to msgs).foreach(_ => producer.sendBody("direct:inputCamel", "test")) 56 | 57 | mockEndpoint.assertIsSatisfied() 58 | (System.currentTimeMillis() - initTime) must be_>=(1000l) 59 | 60 | mockEndpoint.reset() 61 | 62 | mockEndpoint.setExpectedMessageCount(msgs) 63 | 64 | val camelInitTime = System.currentTimeMillis() 65 | (1 to msgs).foreach(_ => producer.sendBody("direct:input", "test")) 66 | 67 | mockEndpoint.assertIsSatisfied() 68 | (System.currentTimeMillis() - camelInitTime) must be_>=(1000l) 69 | } 70 | 71 | "throttle message flow with a function" in new camel { 72 | 73 | val msgs = 3 74 | 75 | //#doc:babel-camel-throttler 76 | 77 | val routeDef = new RouteBuilder { 78 | from("direct:input"). 79 | //throttle message to 1 per second 80 | throttle(_ => 1). 81 | to("mock:output") 82 | } 83 | //#doc:babel-camel-throttler 84 | 85 | val nativeRoute = new CRouteBuilder() { 86 | def configure(): Unit = { 87 | from("direct:inputCamel"). 88 | throttle(1). 89 | to("mock:output") 90 | } 91 | } 92 | 93 | routeDef.addRoutesToCamelContext(camelContext) 94 | camelContext.addRoutes(nativeRoute) 95 | 96 | camelContext.start() 97 | 98 | val mockEndpoint = camelContext.getEndpoint("mock:output").asInstanceOf[MockEndpoint] 99 | 100 | mockEndpoint.setExpectedMessageCount(msgs) 101 | 102 | val producer = camelContext.createProducerTemplate() 103 | 104 | val initTime = System.currentTimeMillis() 105 | (1 to msgs).foreach(_ => producer.sendBody("direct:inputCamel", "test")) 106 | 107 | mockEndpoint.assertIsSatisfied() 108 | (System.currentTimeMillis() - initTime) must be_>=(1000l) 109 | 110 | mockEndpoint.reset() 111 | 112 | mockEndpoint.setExpectedMessageCount(msgs) 113 | 114 | val camelInitTime = System.currentTimeMillis() 115 | (1 to msgs).foreach(_ => producer.sendBody("direct:input", "test")) 116 | 117 | mockEndpoint.assertIsSatisfied() 118 | (System.currentTimeMillis() - camelInitTime) must be_>=(1000l) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/ValidationSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.test.camel 12 | import org.apache.camel.CamelExecutionException 13 | import org.apache.camel.builder.Builder 14 | import org.apache.camel.component.mock.MockEndpoint 15 | import org.specs2.mutable.SpecificationWithJUnit 16 | 17 | class ValidationSpec extends SpecificationWithJUnit { 18 | sequential 19 | 20 | "A validation" should { 21 | 22 | "validate with a predicate" in new camel { 23 | 24 | import io.xtech.babel.camel.builder.RouteBuilder 25 | 26 | //#doc:babel-camel-validate-1 27 | 28 | val routeBuilder = new RouteBuilder { 29 | 30 | from("direct:input").as[Int]. 31 | validate(Builder.body().isEqualTo(1)). 32 | to("mock:output") 33 | } 34 | //#doc:babel-camel-validate-1 35 | 36 | camelContext.addRoutes(routeBuilder) 37 | 38 | camelContext.start() 39 | 40 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 41 | 42 | mock.expectedBodiesReceived(1: java.lang.Integer) 43 | 44 | val template = camelContext.createProducerTemplate() 45 | 46 | template.sendBody("direct:input", 1) 47 | 48 | mock.assertIsSatisfied() 49 | } 50 | 51 | "validate with a function taking a message" in new camel { 52 | 53 | import io.xtech.babel.camel.builder.RouteBuilder 54 | 55 | //#doc:babel-camel-validate-2 56 | 57 | val routeBuilder = new RouteBuilder { 58 | 59 | from("direct:input").as[Int]. 60 | validate(msg => msg.body == Some(1)). 61 | to("mock:output") 62 | } 63 | //#doc:babel-camel-validate-2 64 | 65 | camelContext.addRoutes(routeBuilder) 66 | 67 | camelContext.start() 68 | 69 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 70 | 71 | mock.expectedBodiesReceived(1: java.lang.Integer) 72 | 73 | val template = camelContext.createProducerTemplate() 74 | 75 | template.sendBody("direct:input", 1) 76 | 77 | mock.assertIsSatisfied() 78 | } 79 | 80 | "validate with a function taking a body" in new camel { 81 | 82 | import io.xtech.babel.camel.builder.RouteBuilder 83 | 84 | //#doc:babel-camel-validate-3 85 | 86 | val routeBuilder = new RouteBuilder { 87 | 88 | from("direct:input").as[Int]. 89 | validateBody(body => body == 1). 90 | to("mock:output") 91 | } 92 | //#doc:babel-camel-validate-3 93 | 94 | camelContext.addRoutes(routeBuilder) 95 | 96 | camelContext.start() 97 | 98 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 99 | 100 | mock.expectedBodiesReceived(1: java.lang.Integer) 101 | 102 | val template = camelContext.createProducerTemplate() 103 | 104 | template.sendBody("direct:input", 1) 105 | 106 | mock.assertIsSatisfied() 107 | } 108 | 109 | "through an exception if the message is not valid" in new camel { 110 | 111 | import io.xtech.babel.camel.builder.RouteBuilder 112 | 113 | val routeBuilder = new RouteBuilder { 114 | 115 | from("direct:input").as[Int]. 116 | validateBody(body => body == 123). 117 | to("mock:output") 118 | } 119 | 120 | camelContext.addRoutes(routeBuilder) 121 | 122 | camelContext.start() 123 | 124 | val mock = camelContext.getEndpoint("mock:output", classOf[MockEndpoint]) 125 | 126 | val template = camelContext.createProducerTemplate() 127 | 128 | template.sendBody("direct:input", 1) must throwAn[CamelExecutionException] 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/WireTapSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import io.xtech.babel.camel.mock._ 12 | import io.xtech.babel.camel.test.camel 13 | import org.apache.camel.builder.{ RouteBuilder => CRouteBuilder } 14 | import org.specs2.mutable.SpecificationWithJUnit 15 | 16 | class WireTapSpec extends SpecificationWithJUnit { 17 | sequential 18 | 19 | "create a wire-tap" in new camel { 20 | 21 | val testMessage = "test" 22 | val wireTapMessage = "tap" 23 | 24 | import io.xtech.babel.camel.builder.RouteBuilder 25 | 26 | val routeDef = new RouteBuilder { 27 | //#doc:babel-camel-wiretap 28 | from("direct:input-babel"). 29 | //Incoming messages are sent to the direct endpoint 30 | // and to the next mock endpoint 31 | wiretap("direct:babel-tap") 32 | .to("mock:output-babel") 33 | //#doc:babel-camel-wiretap 34 | 35 | from("direct:babel-tap").processBody(_ => { 36 | Thread.sleep(1000); 37 | "tap" 38 | }).to("mock:output-babel").to("mock:babel-tap") 39 | } 40 | 41 | val nativeRoute = new CRouteBuilder() { 42 | def configure(): Unit = { 43 | from("direct:input-camel").wireTap("direct:camel-tap") 44 | .to("mock:output-camel") 45 | 46 | from("direct:camel-tap").delay(1000).setBody(constant("tap")).to("mock:output-camel").to("mock:camel-tap") 47 | } 48 | } 49 | 50 | routeDef.addRoutesToCamelContext(camelContext) 51 | camelContext.addRoutes(nativeRoute) 52 | 53 | camelContext.start() 54 | 55 | val mockEndpointB = camelContext.mockEndpoint("output-babel") 56 | val mockEndpointBT = camelContext.mockEndpoint("babel-tap") 57 | val mockEndpointC = camelContext.mockEndpoint("output-camel") 58 | val mockEndpointCT = camelContext.mockEndpoint("camel-tap") 59 | 60 | mockEndpointB.expectedBodiesReceived(testMessage, wireTapMessage) 61 | mockEndpointBT.expectedBodiesReceived(wireTapMessage) 62 | mockEndpointC.expectedBodiesReceived(testMessage, wireTapMessage) 63 | mockEndpointCT.expectedBodiesReceived(wireTapMessage) 64 | 65 | val producer = camelContext.createProducerTemplate() 66 | 67 | producer.sendBody("direct:input-camel", testMessage) 68 | producer.sendBody("direct:input-babel", testMessage) 69 | 70 | mockEndpointC.assertIsSatisfied() 71 | mockEndpointCT.assertIsSatisfied() 72 | mockEndpointB.assertIsSatisfied() 73 | mockEndpointBT.assertIsSatisfied() 74 | 75 | } 76 | 77 | "create a functionnal wire-tap" in new camel { 78 | 79 | val testMessage = "test" 80 | val wireTapMessage = "tap" 81 | 82 | import io.xtech.babel.camel.builder.RouteBuilder 83 | 84 | val routeDef = new RouteBuilder { 85 | //#doc:babel-camel-wiretap-functional 86 | from("direct:input-babel"). 87 | //Incoming messages are sent to the direct endpoint 88 | // and to the next mock endpoint 89 | sideEffect(_.to("mock:in-wire").processBody(_ => wireTapMessage).to("mock:out-wire")) 90 | .to("mock:output") 91 | //#doc:babel-camel-wiretap-functional 92 | 93 | } 94 | 95 | routeDef.addRoutesToCamelContext(camelContext) 96 | 97 | camelContext.start() 98 | 99 | val mockEndpointBI = camelContext.mockEndpoint("in-wire") 100 | val mockEndpointBO = camelContext.mockEndpoint("out-wire") 101 | val mockEndpointBT = camelContext.mockEndpoint("output") 102 | 103 | mockEndpointBI.expectedBodiesReceived(testMessage) 104 | mockEndpointBO.expectedBodiesReceived(wireTapMessage) 105 | mockEndpointBT.expectedBodiesReceived(testMessage) 106 | 107 | val producer = camelContext.createProducerTemplate() 108 | 109 | producer.sendBody("direct:input-babel", testMessage) 110 | 111 | mockEndpointBI.assertIsSatisfied() 112 | mockEndpointBO.assertIsSatisfied() 113 | mockEndpointBT.assertIsSatisfied() 114 | 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/builder/RouteBuilderSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.builder 10 | 11 | import io.xtech.babel.camel.test.springContext 12 | import org.apache.camel.CamelContext 13 | import org.apache.camel.component.mock.MockEndpoint 14 | import org.specs2.mutable.SpecificationWithJUnit 15 | 16 | class RouteBuilderSpec extends SpecificationWithJUnit { 17 | sequential 18 | 19 | "Babel Camel route builder" should { 20 | "be defined by the packageScan" in new springContext("classpath:/META-INF/spring/context.xml") { 21 | val context: CamelContext = spring.getBean(classOf[CamelContext]) 22 | val mock = context.getEndpoint("mock:babel-rb").asInstanceOf[MockEndpoint] 23 | mock.expectedBodiesReceived("Hello RB 1", "Hello RB 2") 24 | val producer = context.createProducerTemplate() 25 | producer.sendBody("direct:babel-rb-1", "Hello RB 1") 26 | producer.sendBody("direct:babel-rb-2", "Hello RB 2") 27 | mock.assertIsSatisfied should not(throwA[Exception]) 28 | } 29 | /* 30 | "accept injection base on setter" in new springContext("classpath:/META-INF/spring/context-setter-injection.xml") { 31 | val context: CamelContext = spring.getBean(classOf[CamelContext]) 32 | 33 | val mock = context.getEndpoint("mock:babel-rb-setter").asInstanceOf[MockEndpoint] 34 | mock.expectedBodiesReceived("Hello RB 1bla") 35 | val producer = context.createProducerTemplate() 36 | producer.sendBody("direct:babel-rb-setter", "Hello RB 1") 37 | mock.assertIsSatisfied should not(throwA[Exception]) 38 | } //.pendingUntilFixed("refactor Babel Camel RouteBuilder to support setter injection") 39 | 40 | "accept injection base on constructor" in new springContext("classpath:/META-INF/spring/context-constructor-injection.xml") { 41 | val context: CamelContext = spring.getBean(classOf[CamelContext]) 42 | 43 | val mock = context.getEndpoint("mock:babel-rb-setter").asInstanceOf[MockEndpoint] 44 | mock.expectedBodiesReceived("Hello RB 1bla") 45 | val producer = context.createProducerTemplate() 46 | producer.sendBody("direct:babel-rb-setter", "Hello RB 1") 47 | mock.assertIsSatisfied should not(throwA[Exception]) 48 | } //.pendingUntilFixed("message about the issue") 49 | */ 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/builder/spring/MyRouteBuilder.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | //#doc:babel-camel-spring 10 | package io.xtech.babel.camel.builder.spring 11 | 12 | import io.xtech.babel.camel.builder.RouteBuilder 13 | 14 | class MyRouteBuilder extends RouteBuilder { 15 | from("direct:babel-rb-1").routeId("route1").to("mock:babel-rb") 16 | from("direct:babel-rb-2").routeId("route2").to("mock:babel-rb") 17 | } 18 | 19 | //#doc:babel-camel-spring 20 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/builder/springinjection/SetterInjectionRouteBuilder.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.builder.springinjection 10 | 11 | import io.xtech.babel.camel.builder.{ RouteBuilder, SpringRouteBuilder } 12 | import org.springframework.stereotype.Component 13 | 14 | @Component 15 | class MyBeanProcessor { 16 | def doSomething(str: String): String = str + "bla" 17 | } 18 | 19 | //#doc:babel-camel-spring-setter 20 | 21 | import org.springframework.beans.factory.annotation.Autowired 22 | 23 | import scala.beans.BeanProperty 24 | 25 | class SetterInjectionRouteBuilder extends SpringRouteBuilder { 26 | 27 | @Autowired 28 | @BeanProperty 29 | var aBean: MyBeanProcessor = _ 30 | 31 | def configure(): Unit = { 32 | from("direct:babel-rb-setter").as[String]. 33 | processBody(aBean.doSomething). 34 | to("mock:babel-rb-setter") 35 | } 36 | } 37 | 38 | //#doc:babel-camel-spring-setter 39 | 40 | class ConstructorInjectionRouteBuilder @Autowired() (aBean: MyBeanProcessor) extends RouteBuilder { 41 | 42 | from("direct:babel-rb-setter").bean(aBean).to("mock:babel-rb-setter") 43 | } 44 | 45 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/sample/SampleSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.sample 10 | 11 | import io.xtech.babel.camel.builder.{ RouteBuilder => BabelRouteBuilder } 12 | import io.xtech.babel.camel.mock._ 13 | import io.xtech.babel.camel.test.camel 14 | import io.xtech.babel.fish.model.Message 15 | import org.specs2.mutable.SpecificationWithJUnit 16 | 17 | class SampleSpec extends SpecificationWithJUnit { 18 | sequential 19 | 20 | "Babel Camel Samples" should { 21 | "first typed and functional sample" in new camel { 22 | 23 | //#doc:babel-camel-sample-1 24 | 25 | val routeDef = new BabelRouteBuilder { 26 | 27 | val splitString = (body: String) => body.split(",").toList 28 | 29 | val isForSwitzerland = (msg: Message[String]) => msg.body.fold(false)(_ == "CH") 30 | 31 | val isForGermany = (msg: Message[String]) => msg.body.fold(false)(_ == "D") 32 | 33 | val filterGermanyErrors = (msg: Message[String]) => { 34 | !msg.headers.contains("GermanyCurrencyFailure") 35 | } 36 | 37 | val isForFrance = (msg: Message[String]) => msg.body.fold(false)(_ == "F") 38 | 39 | from("direct:input").as[String] 40 | .processBody(splitString) 41 | .splitBody(list => list.iterator) 42 | .processBody(string => string.toUpperCase) 43 | .choice { 44 | c => 45 | c.when(isForSwitzerland).to("mock:switzerland") 46 | c.when(isForFrance).to("mock:france") 47 | c.when(isForGermany).filter(filterGermanyErrors).to("mock:germany") 48 | } 49 | .to("mock:output") 50 | } 51 | 52 | //#doc:babel-camel-sample-1 53 | 54 | routeDef.addRoutesToCamelContext(camelContext) 55 | 56 | camelContext.start() 57 | 58 | val mockEndpointF = camelContext.mockEndpoint("france") 59 | mockEndpointF.expectedBodiesReceived("F") 60 | 61 | val mockEndpointCH = camelContext.mockEndpoint("switzerland") 62 | mockEndpointCH.expectedBodiesReceived("CH") 63 | 64 | val producer = camelContext.createProducerTemplate() 65 | producer.sendBody("direct:input", "ch,f,d") 66 | 67 | mockEndpointF.assertIsSatisfied() 68 | mockEndpointCH.assertIsSatisfied() 69 | } 70 | 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/test/SpecsContexts.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.test 10 | 11 | import org.apache.camel.Exchange 12 | import org.apache.camel.impl.{ DefaultCamelContext, DefaultExchange } 13 | import org.specs2.mutable.After 14 | import org.springframework.context.support.ClassPathXmlApplicationContext 15 | 16 | /** 17 | * Declare a CamelContext in the Context of a Specs2 example. 18 | */ 19 | class camel extends After { 20 | 21 | lazy implicit val camelContext = new DefaultCamelContext() 22 | 23 | def createExchange(): Exchange = new DefaultExchange(camelContext) 24 | 25 | def after: Unit = { 26 | camelContext.shutdown() 27 | } 28 | } 29 | 30 | /** 31 | * Declare a Spring Application Context in the Context of a Specs2 example. 32 | * @param configLocation the location of a spring xml file. 33 | */ 34 | class springContext(configLocation: String) extends After { 35 | 36 | lazy val spring = new ClassPathXmlApplicationContext(configLocation) 37 | 38 | def after: Unit = { 39 | spring.close() 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/test/SpringSpecification.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel.test 10 | 11 | import org.apache.camel.ProducerTemplate 12 | import org.apache.camel.component.mock.MockEndpoint 13 | import org.apache.camel.model.ModelCamelContext 14 | import org.specs2.mutable.SpecificationWithJUnit 15 | import org.specs2.specification.{ AfterExample, BeforeExample, Fragments, Step } 16 | import org.springframework.context.ApplicationContext 17 | import org.springframework.context.support.AbstractApplicationContext 18 | 19 | import scala.reflect._ 20 | 21 | trait SpringSpecification { 22 | 23 | type ContextType <: ApplicationContext 24 | 25 | def applicationContext: ContextType 26 | 27 | def bean[A: ClassTag]: A = applicationContext.getBean(classTag[A].runtimeClass.asInstanceOf[Class[A]]) 28 | } 29 | 30 | trait CamelSpecification { 31 | self: SpringSpecification => 32 | 33 | def camelContext: ModelCamelContext = applicationContext.getBean(classOf[ModelCamelContext]) 34 | 35 | def mockEndpoint(uri: String): MockEndpoint = camelContext.getEndpoint(uri, classOf[MockEndpoint]) 36 | 37 | def producerTemplate(): ProducerTemplate = camelContext.createProducerTemplate() 38 | } 39 | 40 | /** 41 | * Base class for Babel Camel tests. The same Application Context is used for the Specification. 42 | */ 43 | trait CachedBabelSpringSpecification extends SpecificationWithJUnit with SpringSpecification with CamelSpecification { 44 | 45 | /** 46 | * Type of the Application Context 47 | */ 48 | type ContextType <: AbstractApplicationContext 49 | 50 | /** 51 | * The Application Context used by all the tests of this Specification. 52 | */ 53 | val applicationContext: ContextType 54 | 55 | private[this] def startContext(): Unit = { 56 | applicationContext.start() 57 | } 58 | 59 | private[this] def stopContext(): Unit = { 60 | applicationContext.close() 61 | } 62 | 63 | /** the map method allows to "post-process" the fragments after their creation */ 64 | override def map(fs: => Fragments): Fragments = Step(startContext()) ^ fs ^ Step(stopContext()) 65 | } 66 | 67 | /** 68 | * Base class for Babel Camel tests. An application context is created for each tests. 69 | */ 70 | trait BabelSpringSpecification extends SpecificationWithJUnit with SpringSpecification with CamelSpecification with BeforeExample with AfterExample { 71 | 72 | private[this] var appContext: Option[ContextType] = _ 73 | 74 | /** 75 | * Type of the Application Context 76 | */ 77 | type ContextType <: AbstractApplicationContext 78 | 79 | def applicationContext: ContextType = appContext.get 80 | 81 | /** 82 | * A factory of Application Context used by each tests. 83 | */ 84 | val applicationContextFactory: () => ContextType 85 | 86 | def before: Unit = { 87 | val context = applicationContextFactory() 88 | appContext = Some(context) 89 | context.start() 90 | } 91 | 92 | def after: Unit = { 93 | appContext.foreach(_.stop()) 94 | appContext = None 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-mock/build.sbt: -------------------------------------------------------------------------------- 1 | 2 | organization := "io.xtech.babel" 3 | 4 | name := "babel-camel-mock" 5 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-mock/src/main/scala/io/xtech/babel/camel/mock/MockDSL.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | //#doc:babel-mock 10 | 11 | package io.xtech.babel.camel.mock 12 | 13 | import io.xtech.babel.fish.model.StepDefinition 14 | import io.xtech.babel.fish.parsing.{ Parsing, StepInformation } 15 | import io.xtech.babel.fish.{ BaseDSL, DSL2BaseDSL } 16 | import org.apache.camel.builder.RouteBuilder 17 | import org.apache.camel.model.ProcessorDefinition 18 | 19 | import scala.collection.immutable 20 | import scala.language.implicitConversions 21 | import scala.reflect.ClassTag 22 | 23 | case class MockDefinition(filePath: String) extends StepDefinition 24 | 25 | class MockDSL[I: ClassTag](protected val baseDsl: BaseDSL[I]) extends DSL2BaseDSL[I] { 26 | 27 | /** 28 | * The mock keyword. Stores received exchanges in order to assert properties in tests. 29 | * @param endpointUri target mock endpoint which translates to "mock:endpointUri" 30 | * @see io.xtech.babel.camel.mock 31 | * @return the possibility to add other steps to the current DSL 32 | */ 33 | def mock(endpointUri: String): BaseDSL[I] = MockDefinition(endpointUri) 34 | } 35 | 36 | trait Mock extends Parsing[RouteBuilder] { 37 | 38 | val parse: Process = { 39 | case StepInformation(MockDefinition(uri), camelProcessor: ProcessorDefinition[_]) => 40 | camelProcessor.to(s"mock:$uri") 41 | 42 | } 43 | 44 | abstract override protected def steps: immutable.Seq[Process] = super.steps :+ parse 45 | 46 | implicit protected def mockDSLExtension[I: ClassTag](baseDsl: BaseDSL[I]): MockDSL[I] = new MockDSL(baseDsl) 47 | } 48 | 49 | //#doc:babel-mock 50 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-mock/src/main/scala/io/xtech/babel/camel/mock/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import org.apache.camel.CamelContext 12 | import org.apache.camel.component.mock.MockEndpoint 13 | 14 | package object mock { 15 | 16 | implicit class CamelContextWithMock(val self: CamelContext) extends AnyVal { 17 | 18 | def getMockEndpoint(uri: String): MockEndpoint = mockEndpoint(uri) 19 | 20 | def mockEndpoint(uri: String): MockEndpoint = self.getEndpoint(s"mock:$uri").asInstanceOf[MockEndpoint] 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /babel-camel/babel-camel-mock/src/test/scala/io/xtech/babel/camel/MockSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.camel 10 | 11 | import org.apache.camel.builder.RouteBuilder 12 | import org.apache.camel.impl.DefaultCamelContext 13 | import org.apache.camel.{ Exchange, Processor } 14 | import org.specs2.mutable.SpecificationWithJUnit 15 | 16 | class MockSpec extends SpecificationWithJUnit { 17 | sequential 18 | 19 | "camel mock tools" in { 20 | 21 | val camelContext = new DefaultCamelContext() 22 | 23 | import io.xtech.babel.camel.mock._ 24 | 25 | val routeDef = new RouteBuilder { 26 | from("direct:input"). 27 | to("mock:output1"). 28 | process(new Processor { 29 | override def process(exchange: Exchange): Unit = exchange.getIn.setBody(exchange.getIn.getBody(classOf[String]).toUpperCase) 30 | }). 31 | to("mock:output2") 32 | 33 | override def configure(): Unit = {} 34 | } 35 | 36 | routeDef.addRoutesToCamelContext(camelContext) 37 | 38 | camelContext.start() 39 | 40 | val mockEndpoint1 = camelContext.getMockEndpoint("output1") 41 | val mockEndpoint2 = camelContext.mockEndpoint("output2") 42 | 43 | mockEndpoint1.expectedBodiesReceived("test") 44 | mockEndpoint2.expectedBodiesReceived("TEST") 45 | 46 | val producer = camelContext.createProducerTemplate() 47 | 48 | producer.sendBody("direct:input", "test") 49 | 50 | mockEndpoint1.assertIsSatisfied() 51 | mockEndpoint2.assertIsSatisfied() 52 | 53 | camelContext.shutdown() must not(throwA[Exception]) 54 | 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /babel-doc/documentation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #How to use it: just call this script from the project root directory. 4 | 5 | # Setup if you want to use virtual python environment 6 | #virtualenv ENV 7 | #source ./ENV/bin/activate 8 | 9 | sudo pip install --upgrade sphinx sphinx_bootstrap_theme 10 | 11 | cd babel-doc 12 | make clean 13 | 14 | #generate the main documentation 15 | make html 16 | 17 | #generate the main documentation in pdf 18 | make latexpdf 19 | cp build/latex/Babel.pdf build/html/_static/ 20 | 21 | #Clean the python virtual env 22 | cd .. 23 | 24 | #cleaning of the virtual python environment 25 | # deactivate 26 | 27 | -------------------------------------------------------------------------------- /babel-doc/generate-pdf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #generate the documentation in latex format 4 | make latex 5 | 6 | #generate grammar diagrams in png format 7 | for file in source/grammar-diagrams/*.svg 8 | do 9 | output=$(basename $file .svg).png 10 | convert $file $output 11 | mv $output build/latex/ 12 | done 13 | 14 | #change tex images from svg to be png 15 | sed -e 's/svg/png/g' build/latex/Babel.tex > temp.tex 16 | mv temp.tex build/latex/Babel.tex 17 | 18 | #generate the pdf 19 | cd build/latex 20 | pdflatex *.tex 21 | pdflatex *.tex #done twice for table of content 22 | -------------------------------------------------------------------------------- /babel-doc/images/architecture-camel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/images/architecture-camel.png -------------------------------------------------------------------------------- /babel-doc/images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/images/architecture.png -------------------------------------------------------------------------------- /babel-doc/images/logo-without-pole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/images/logo-without-pole.png -------------------------------------------------------------------------------- /babel-doc/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/images/logo.png -------------------------------------------------------------------------------- /babel-doc/images/vectorial/logo.idraw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/images/vectorial/logo.idraw -------------------------------------------------------------------------------- /babel-doc/source/.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | -------------------------------------------------------------------------------- /babel-doc/source/.sphinx/exts/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /babel-doc/source/.static/default.css: -------------------------------------------------------------------------------- 1 | .left { 2 | float: left; 3 | width: 33%; 4 | padding-right: 20px; 5 | } 6 | 7 | .middle { 8 | display: block; 9 | overflow: hidden; 10 | width: 33%; 11 | } 12 | 13 | .right { 14 | padding-left: 20px; 15 | float: right; 16 | width: 33%; 17 | } 18 | 19 | .about { 20 | padding: 10px; 21 | padding-bottom: 30px; 22 | width: 100%; 23 | background-color: rgb(234, 241, 241); 24 | border-bottom-color: rgba(0, 0, 0, 0.1); 25 | border-bottom-width: 1px; 26 | border-bottom-style: solid; 27 | margin-bottom: 20px; 28 | margin-top: 20px; 29 | } 30 | 31 | .alert-info { 32 | background-color: #222222; 33 | } 34 | 35 | .alert-warning { 36 | background-color: #e74c3c; 37 | } 38 | 39 | #dLabelLocalToc { 40 | visibility: hidden; 41 | } 42 | 43 | .localtoc { 44 | visibility: hidden; 45 | } 46 | 47 | #pdf-link { 48 | float: right; 49 | vertical-align: middle; 50 | padding-top: 5px; 51 | padding-bottom: 5px; 52 | padding-left: 10px; 53 | } 54 | 55 | #pdf-link a:link { 56 | color: #FFFFFF; 57 | } 58 | 59 | #pdf-link a:visited { 60 | color: #FFFFFF; 61 | } 62 | .alert-info{ 63 | background-color:#F5F5F5 64 | color: #333 65 | } 66 | -------------------------------------------------------------------------------- /babel-doc/source/.static/eip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/eip.png -------------------------------------------------------------------------------- /babel-doc/source/.static/lambda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/lambda.png -------------------------------------------------------------------------------- /babel-doc/source/.static/language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/language.png -------------------------------------------------------------------------------- /babel-doc/source/.static/modular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/modular.png -------------------------------------------------------------------------------- /babel-doc/source/.static/osgi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/osgi.png -------------------------------------------------------------------------------- /babel-doc/source/.static/type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/.static/type.png -------------------------------------------------------------------------------- /babel-doc/source/.templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {# Custom CSS overrides #} 4 | {% set bootswatch_css_custom = ['_static/default.css'] %} 5 | 6 | {% block header %} 7 | {{ super() }} 8 | 14 | 15 | 28 | 37 | {% endblock %} 38 | 39 | 40 | -------------------------------------------------------------------------------- /babel-doc/source/_themes/bootstrap: -------------------------------------------------------------------------------- 1 | ../../../bootstrap -------------------------------------------------------------------------------- /babel-doc/source/architecture.rst: -------------------------------------------------------------------------------- 1 | .. _babel-architecture: 2 | 3 | Babel Architecture 4 | ================== 5 | 6 | Babel overview 7 | ++++++++++++++ 8 | 9 | Babel is a Domain Specific Language (DSL). This means Babel helps you to specify what you want to achieve and not to make it directly. 10 | 11 | You may see Babel as one more DSL for Apache Camel, among well-known ones such as the Java, Scala and XML DSL: 12 | 13 | .. figure:: ../images/architecture-camel.png 14 | :align: center 15 | :scale: 75% 16 | 17 | Babel Camel is another way to write Apache Camel routes. 18 | 19 | Babel Modules 20 | +++++++++++++ 21 | 22 | Babel is splitted into modules: 23 | 24 | * **babel-fish** is the core of Babel 25 | * **babel-camel** is a connector for Apache Camel 26 | * **babel-spring** is an experimental connector for Spring Integration (coming soon) 27 | 28 | .. figure:: ../images/architecture.png 29 | :align: center 30 | :scale: 75% 31 | 32 | Babel's modules : **babel-fish**, **babel-camel** and the experimental **babel-spring** -------------------------------------------------------------------------------- /babel-doc/source/camel/mock.rst: -------------------------------------------------------------------------------- 1 | 2 | Mock Extension 3 | =============== 4 | 5 | Mock is the first extension of the Babel Camel DSL. It provides both a DSL and some helpers. 6 | 7 | Description 8 | +++++++++++ 9 | 10 | An extension for Babel Camel declaring some helpers for testing. 11 | 12 | Requirement 13 | ~~~~~~~~~~~ 14 | 15 | The ``babel-camel-mock`` module needs to in the classpath. 16 | 17 | Usage 18 | +++++ 19 | 20 | Import the ``io.xtech.babel.camel.mock._`` package and extends the ``RouteBuilder`` with the ``Mock`` trait. 21 | 22 | mock component 23 | ~~~~~~~~~~~~~~ 24 | 25 | For testing a mock endpoint can be declared with the mock endpoint. 26 | 27 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/MockSpec.scala#doc:babel-camel-mock 28 | 29 | The mock keyword keeps the type of the payload as the mock component do not modify the received messages in most of the cases. For more complexe cases, such as when using ``returnReplyBody``, you may fallback to the legacy way to define mock endpoints. 30 | 31 | -------------------------------------------------------------------------------- /babel-doc/source/camel/samples.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel Camel Samples 3 | =================== 4 | 5 | Process - Split - Router Sample 6 | +++++++++++++++++++++++++++++++ 7 | 8 | This snippet of code defines a Route which receives a list of country id and dispatch to the corresponding country. 9 | 10 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/sample/SampleSpec.scala#doc:babel-camel-sample-1 -------------------------------------------------------------------------------- /babel-doc/source/camel/spring.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel Camel using the Spring Application Context 3 | ================================================ 4 | 5 | This page explains how to integrate a Babel Camel route with a Spring Application Context. 6 | 7 | A route defined with the Babel Camel DSL may be transparently loaded into a Spring Application Context, such as that: 8 | 9 | .. highlight:: xml 10 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/resources/META-INF/spring/context.xml 11 | .. highlight:: scala 12 | 13 | With the corresponding Babel Camel route: 14 | 15 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/builder/spring/MyRouteBuilder.scala#doc:babel-camel-spring 16 | 17 | .. warning:: Unfortunately, the injection using setters may cause Babel initialization to fail because Babel may get intialized before every required Spring Bean. To handle this, please use the ``io.xtech.cf.babel.camel.builder.SpringRouteBuilder`` and define your route in the *configure* method body. 18 | You may also use the constructor injection if you prefer to rely on the basic ``io.xtech.babel.camel.builder.RouteBuilder``. 19 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/builder/springinjection/SetterInjectionRouteBuilder.scala#doc:babel-camel-spring-setter -------------------------------------------------------------------------------- /babel-doc/source/cameluserguide.rst: -------------------------------------------------------------------------------- 1 | .. _babel-camel-guide: 2 | 3 | Babel Camel User guide 4 | ====================== 5 | 6 | .. todo : be able to create a pdf only for babel camel user guide 7 | 8 | 9 | In most examples, we are writing a `route` which represents the flow of your integration solution. Those `routes` are usually defined in a 10 | `RouteBuilder`. 11 | Most of the keywords are dealing with the Camel Message, unless specified as body specific (for example, **process** deals with a Camel Message and **processBody** deals with the body of the Camel Message). 12 | 13 | .. warning:: 14 | In the Message interface, its body is represented as an Option[T] to handle the nullable case. Thus, the keywords, such as **process**, which handles a Message should be aware of this point. The keywords, such as **processBody**, which handles directly the Message body do not have to care about that. 15 | 16 | .. toctree:: 17 | :maxdepth: 2 18 | 19 | camel/spring 20 | camel/samples 21 | camel/basics 22 | camel/transformation 23 | camel/routing 24 | camel/errormanagement 25 | camel/mock 26 | 27 | -------------------------------------------------------------------------------- /babel-doc/source/dev/contribute.rst: -------------------------------------------------------------------------------- 1 | 2 | Contribute to Babel 3 | =================== 4 | 5 | First of all, thank you for wanting to improve the Babel project. These guidelines may help you in your trip to enrich Babel with your skills, whatever they are. 6 | 7 | How to contribute? 8 | ++++++++++++++++++ 9 | 10 | Contribute with feedback 11 | ~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | Maybe the first way to contribute to the Babel project is to test it and to provide us feedback about your experience. 14 | 15 | First, even if it may be obvious, have a look to the current documentation, the existing posts in the mailing list and the github issues. As computer scientists, we love when not repeating ourselves unnecessary. 16 | 17 | The best place to ask your questions (and potentially to get answer) is the `mailing list `_ . 18 | You may also (but not always) chat in our irc room (at irc.codehaus.net, channel #babel) 19 | 20 | 21 | Contribute with code 22 | ~~~~~~~~~~~~~~~~~~~~ 23 | 24 | We will examine and hopefully accept your code contribution with pleasure. Please have a look to the following points which may help you to contribute: 25 | 26 | * Read and sign the `CLA `_ . 27 | * Make sure a github issue exists (to avoid other people to work on the same topic). 28 | * Ensure your using the Crossing-Tech `copyright `_, you are not addding dependencies incompatible with the licence Apache2. 29 | * Shape your contribution into a Github `Pull request `_ . 30 | * Please take the Pull request review as an opportunity to improve the quality of your contribution. Creating the Pull request is certainly not your the final goal. 31 | * Once the Pull requested is accepted, please clean your git branch (it should be more often a single commit). 32 | 33 | We would like to keep the contribution process as simple and effective as possible. This procedure may get improve with the time, do not hesitate if you have an opinion. 34 | 35 | .. toctree:: 36 | :hidden: 37 | 38 | legal -------------------------------------------------------------------------------- /babel-doc/source/dev/development.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel development 3 | ================= 4 | 5 | .. highlight:: bash 6 | 7 | We will define here some guide lines used during the development of Babel. 8 | 9 | Build 10 | +++++ 11 | 12 | Babel is build using Apache Maven (even if a Sbt configuration is synchronized with). 13 | 14 | Source Code 15 | +++++++++++ 16 | 17 | The Code is reformatted while compiling the sources using sbt (which uses `scalariform `_) 18 | To reformat the code: 19 | :: 20 | 21 | sbt test-compile 22 | 23 | Tests 24 | +++++ 25 | 26 | In the Babel modules implemented using Scala, `Specs2 `_ is the used testing framework. 27 | 28 | Test coverage reports are generated using scoverage through the sbt build configuration following: 29 | :: 30 | 31 | sbt scoverage:test 32 | #browse test reports in modules target directory (target/classes/coverage-report) 33 | 34 | Deployment 35 | +++++++++++ 36 | 37 | With Maven 38 | ~~~~~~~~~~ 39 | Snapshots are deployed locally using the Maven build configuration as following: 40 | :: 41 | 42 | mvn install 43 | 44 | With Sbt 45 | ~~~~~~~~ 46 | Snapshots are deployed using the Sbt build configuration as following: 47 | :: 48 | 49 | sbt publish-local 50 | 51 | Release 52 | +++++++ 53 | 54 | Releases are done using the Sbt/Maven build configuration (coming soon) 55 | 56 | 57 | .. highlight:: scala -------------------------------------------------------------------------------- /babel-doc/source/dev/extension.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _babel-dev-extension: 3 | 4 | Babel Extension creation 5 | ======================== 6 | 7 | This page will explains how you can extends the DSL from Babel Camel by adding new keywords and grammar parts to the existing DSL. 8 | 9 | .. warning:: 10 | The extension of the DSL requires some knowledge of the Scala language. 11 | 12 | Existing Extensions 13 | +++++++++++++++++++ 14 | 15 | .. toctree:: 16 | :maxdepth: 1 17 | 18 | ../camel/mock 19 | 20 | Create an extension 21 | +++++++++++++++++++ 22 | 23 | To create an extension, you need to create a new DSL, some definition objects and a Parser. 24 | 25 | Explanation 26 | ~~~~~~~~~~~ 27 | 28 | #. Choose a package for your the new extension like ``io.xtech.babel.camel.mock`` 29 | #. Create some definition objects that extends ``io.xtech.babel.fish.parsing.StepDefinition``. 30 | #. Create a DSL with your new keywords using the definition objects. 31 | The DSL will take a ``io.xtech.babel.fish.BaseDSL`` and extends a ``io.xtech.babel.fish.DSL2BaseDSL`` 32 | #. Create a trait that extends ``io.xtech.babel.camel.parsing.CamelParsing``. 33 | 34 | a) Declare your parser by defining a parse method which returns a ``Process`` type and add it to the ``steps`` of the trait. 35 | b) Declare an implicit method using your new DSL. 36 | 37 | Example 38 | ~~~~~~~ 39 | .. includecode:: ../../../babel-camel/babel-camel-core/src/test/scala/io/xtech/babel/camel/MockSpec.scala#doc:babel-camel-mock 40 | 41 | -------------------------------------------------------------------------------- /babel-doc/source/dev/installation.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel Installation Guide 3 | ======================== 4 | 5 | 6 | Project Requirements 7 | ++++++++++++++++++++ 8 | 9 | =========================== ======================================== 10 | Operating System GNU/Linux, Mac OS X, MS Windows 11 | Java VM Oracle JDK 6 12 | Maven 3.0.5 13 | =========================== ======================================== 14 | 15 | .. _MavenInstall: 16 | 17 | Build Babel with Maven 18 | ++++++++++++++++++++++ 19 | 20 | .. highlight:: bash 21 | 22 | To build Babel from sources using `Apache Maven `_, in a regular shell:: 23 | 24 | git clone https://github.com/babel-dsl/babel.git 25 | cd babel 26 | export MAVEN_OPTS="-XX:MaxPermSize=256m -Xmx1024m" 27 | mvn install 28 | 29 | 30 | Build Babel with Sbt 31 | ++++++++++++++++++++ 32 | To build Babel from sources using `Sbt `_, in a regular shell:: 33 | 34 | git clone https://github.com/babel-dsl/babel.git 35 | cd babel 36 | export SBT_OPTS="-XX:MaxPermSize=256m -Xmx1024m" 37 | sbt test publish-local 38 | 39 | .. highlight:: scala 40 | 41 | Generate the documentation 42 | ++++++++++++++++++++++++++ 43 | 44 | to generate the documentation, first install the sphinx documentation generator and then, run: 45 | :: 46 | 47 | git clone https://github.com/babel-dsl/babel.git 48 | cd babel/babel-doc 49 | make html 50 | #browse build/html/index.html 51 | 52 | .. note:: 53 | Akka provides some nice documentation on how to generate documentation with Sphinx: `Akka Sphinx Documentation `_ 54 | -------------------------------------------------------------------------------- /babel-doc/source/dev/legal.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel copyright notice 3 | ====================== 4 | 5 | The copyright notice should look like: 6 | :: 7 | 8 | /* 9 | * 10 | * Copyright STARTING_YEAR-CURRENT_YEAR Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 11 | * All rights reserved. 12 | * 13 | * ================================================================================== 14 | */ 15 | 16 | Where the STARTING_YEAR states the creation of the file and the CURRENT_YEAR states the last modification of the file. 17 | 18 | Please avoid any mention of author information in the file. Instead of this, please make sure your name get mentioned with the first release of your contribution. 19 | -------------------------------------------------------------------------------- /babel-doc/source/dev/structure.rst: -------------------------------------------------------------------------------- 1 | 2 | Babel Structure 3 | =============== 4 | 5 | Each of the presented Babel module is composed of the following objects: 6 | 7 | * Domain Specific Language (DSL) 8 | * Definition Objects (model) 9 | * Parser 10 | 11 | DSL 12 | ~~~ 13 | 14 | - The DSL is used by the user when declaring the flow of a route. 15 | - The DSL exposes an API and creates definition object used by the parser. 16 | 17 | Definition Objects 18 | ~~~~~~~~~~~~~~~~~~ 19 | 20 | - Each definition object defines the behaviour of an EIP in the route. 21 | - All the definitions define the model of the route. 22 | 23 | Parser 24 | ~~~~~~ 25 | 26 | - A parser takes definition objects and use them to configure the runtime of the route (Apache Camel, Spring Integration). 27 | - A route is defined with all its definition objects. 28 | 29 | 30 | -------------------------------------------------------------------------------- /babel-doc/source/devguide.rst: -------------------------------------------------------------------------------- 1 | Babel Development guide 2 | ======================= 3 | 4 | This sections provides information if you want to develop or understand better Babel. 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | 9 | dev/structure 10 | dev/installation 11 | dev/development 12 | dev/contribute 13 | dev/extension -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/grammar-diagrams/handler-1.png -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-1.svg: -------------------------------------------------------------------------------- 1 | class RouteBuilder{handlefrom.handle} -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/grammar-diagrams/handler-2.png -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-2.svg: -------------------------------------------------------------------------------- 1 | handle(_.error-handlingroute=>{route.error-handling}) -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/grammar-diagrams/handler-3.png -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-3.svg: -------------------------------------------------------------------------------- 1 | on[Exception](Predicate)continued(BooleanPredicate)handled(BooleanPredicate) -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Crossing-Tech/babel/c2bfe0b76fe18cf95bdfdce75e0cf90f01fa146a/babel-doc/source/grammar-diagrams/handler-4.png -------------------------------------------------------------------------------- /babel-doc/source/grammar-diagrams/handler-4.svg: -------------------------------------------------------------------------------- 1 | defaultErrorHandlerdeadletter(String ).maximumRedeliveries(Integer ).maximumRedeliveries(Long ).maximumRedeliveryDelay(Integer )loggingErrorHandler(LoggingLevelLogger)noErrorHandler -------------------------------------------------------------------------------- /babel-doc/source/grammar.g: -------------------------------------------------------------------------------- 1 | route ::= 'from(' string ')' ( '.on[' Exception.Type ']' ( 'when' ( BODYPREDICATE | FUNCTION ) )? optionalConfiguration | '.onMessage[' Exception.Type ']' ( 'when' ( MESSAGEPREDICATE | FUNCTION ) )? optionalConfiguration )? -------------------------------------------------------------------------------- /babel-doc/source/grammar/handler.grammar: -------------------------------------------------------------------------------- 1 | RouteBuilder = 'class RouteBuilder' '{' [handle] ('from' [ '.'handle])+ '}'; 2 | handle = 'handle' '('('_.' 'error-handling' | 'route' '=>' '{' { 'route' '.' 'error-handling' } '}')')'; 3 | exceptionClause = 'on' '[' Exception ']'['(' Predicate ')'] ('continued' '(' (Boolean | Predicate) ')' | 'handled' '(' (Boolean | Predicate) ')'); 4 | errorHandler = (('defaultErrorHandler'|'deadletter(' String' )') ['.maximumRedeliveries(' Integer' )'] ['.maximumRedeliveries(' Long' )'] ['.maximumRedeliveryDelay(' Integer' )']) | 'loggingErrorHandler' '('[LoggingLevel] [Logger] ')'| 'noErrorHandler' ) -------------------------------------------------------------------------------- /babel-doc/source/opinion.rst: -------------------------------------------------------------------------------- 1 | .. _babel-opinion: 2 | 3 | Babel Opinion 4 | ============= 5 | 6 | Babel opinion is that code which defines integration should be easy to write and to read. From the experience we have got using Apache Camel (Java DSL), we have raise the following points: 7 | 8 | - A DSL needs to be simple to make it easy to write 9 | - A DSL needs to be explicit to make it easy to read 10 | 11 | We have been influenced by the `Scala `_ language. In other words, we just want to have the same features we already had with Scala at the route layer. Let's take a look at those points: 12 | 13 | Simple DSL 14 | ++++++++++ 15 | 16 | Simple means we would provide one way to do things. This means selection. Currently, the amount of possibilities does not facilitate the coding process. 17 | 18 | Actually, "simple" means composed by one thing, without duplicity nor ornamentation but plain. At this point, simple means also easy in the sense we have tried to restrict the possibilities to the most interesting. Babel adds as less as possible new Interfaces and tries as much as possible to rely on existing and basic tools such as Functions. As we will see latter, clear auto-completion provided by your IDE increase the coding process and adds confidence into what you are actually writing. Select the best way to achieve your task and then *transform a good practice into API* could be the main goal of the Babel project. 19 | 20 | Explicit DSL 21 | ++++++++++++ 22 | 23 | As a first taste, explicit means to avoid some implicits. In Apache Camel, an implict we found really dangerous and not advantageous was the Implict type converters: Apache Camel implicitely add type conversion depending on your code expectations. 24 | In other words, with Apache Camel, if your code expects some type concerning its input which is not the output of the previous step, this will be fixed implicitely at runtime. 25 | On the contrary, with Babel, the input type is as explicit as possible. For convenience, it is simply computed from the previous step output. Even if you do not see it in your code, your IDE may compute it at compile time and this is used to validate your code before having actually run it. 26 | 27 | More important is the fact that adding information about the input type helps to read your code (and also to review it). Babel tends also to separate (explicit) type conversion from input transformation. 28 | 29 | Explicit and Simple DSL 30 | +++++++++++++++++++++++ 31 | 32 | Now let's have a look to what does those two feature provide together to the coding process. Actually, we may also resume those two aspects as **typed** and **functional**. 33 | 34 | In other words, Babel lets you define processing in functional way and raise Scala type inference at the route level. 35 | 36 | Auto completion takes advantages from the typing as much as from the simplicity: 37 | 38 | - Having only the possible keywords in completion helps to find the good one 39 | - Type inference checks and provides inputs type to your functions 40 | 41 | -------------------------------------------------------------------------------- /babel-doc/source/quickstartguide.rst: -------------------------------------------------------------------------------- 1 | .. _babel-quick-start: 2 | 3 | Quick start guide 4 | ================= 5 | 6 | Babel depends mainly on the following artifacts: 7 | 8 | * org.scala-lang/scala-library/2.10.4 9 | * org.apache.camel/camel-core/2.12.4 10 | 11 | Using Maven 12 | +++++++++++ 13 | 14 | .. highlight:: xml 15 | 16 | To add Babel Camel in a Maven project, just add the following dependencies to your pom.xml file: 17 | 18 | :: 19 | 20 | 21 | io.xtech.babel 22 | babel-camel-core 23 | BABEL_VERSION 24 | 25 | 26 | If you don't want to build the Babel project on your machine (otherwise, see :ref:`MavenInstall`), use the Sonatype Snapshot repository to your Maven configuration:: 27 | 28 | 29 | oss-sonatype 30 | oss-sonatype 31 | https://oss.sonatype.org/content/repositories/snapshots/ 32 | 33 | true 34 | 35 | 36 | 37 | If you also want to use the Babel Camel Mock extension for your tests, you may also add: 38 | 39 | :: 40 | 41 | 42 | io.xtech.babel 43 | babel-camel-mock 44 | BABEL_VERSION 45 | test 46 | 47 | 48 | Where BABEL_VERSION is replaced by the actual Babel version. 49 | 50 | Using Sbt 51 | +++++++++ 52 | 53 | .. highlight:: scala 54 | 55 | To add Babel Camel in a Sbt project, you may just add the following dependencies and resolver to your build configuration: 56 | 57 | :: 58 | 59 | resolvers += "Sonatype OSS Snapshots" at 60 | "https://oss.sonatype.org/content/repositories/snapshots 61 | 62 | libraryDependencies += "io.xtech.babel" %% "babel-camel-core" % "BABEL_VERSION" 63 | //if you want to use the mock keyword to simplify your tests: 64 | libraryDependencies += "io.xtech.babel" %% "babel-camel-mock" % "BABEL_VERSION" 65 | % "test" 66 | 67 | Where BABEL_VERSION is replaced by the actual Babel version. -------------------------------------------------------------------------------- /babel-fish/build.sbt: -------------------------------------------------------------------------------- 1 | 2 | organization := "io.xtech.babel" 3 | 4 | name := "babel-fish" 5 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/DSLHelper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | 13 | import scala.language.implicitConversions 14 | import scala.reflect.ClassTag 15 | 16 | trait DSLEnricher 17 | 18 | /** 19 | * Template DSL whose keywords are typing a BaseDSL 20 | */ 21 | trait DSL2BaseDSL[I] extends DSLEnricher { 22 | 23 | protected def baseDsl: BaseDSL[I] 24 | 25 | protected implicit def addAStepToTheDSL[II: ClassTag](definition: StepDefinition): BaseDSL[II] = { 26 | baseDsl.step.next = Some(definition) 27 | new BaseDSL[II](definition) 28 | } 29 | 30 | } 31 | 32 | /** 33 | * Template DSL whose keywords are typing a FromDSL 34 | */ 35 | trait BaseDSL2FromDSL[I] extends DSLEnricher { 36 | 37 | protected def baseDsl: BaseDSL[I] 38 | 39 | protected implicit def addAStepToTheDSL[II: ClassTag](definition: StepDefinition): FromDSL[II] = { 40 | baseDsl.step.next = Some(definition) 41 | new FromDSL[II](definition) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/JVMLanguage.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish 10 | 11 | /** 12 | * extends a Java function be to read by Scala 13 | */ 14 | trait JVMFunction[-I, +O] { 15 | def apply(input: I): O 16 | } 17 | 18 | /** 19 | * extends a Java predicate to be read by Scala 20 | */ 21 | trait JVMPredicate[-I] { 22 | def apply(input: I): Boolean 23 | } 24 | 25 | /** 26 | * Facility tools for java 8 DSLs 27 | */ 28 | object ScalaHelper { 29 | 30 | def scalaFunction[I, O](function: JVMFunction[I, O]): (I => O) = (i) => { 31 | function.apply(i) 32 | } 33 | 34 | def scalaPredicate[I](predicate: JVMPredicate[I]): (I => Boolean) = (i) => { 35 | predicate.apply(i) 36 | } 37 | } -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/NamingStrategy.scala: -------------------------------------------------------------------------------- 1 | package io.xtech.babel.fish 2 | 3 | import io.xtech.babel.fish.model.StepDefinition 4 | 5 | /** 6 | * The NamingStragegy trait lets define how pattern should be identified in the targeted framework. 7 | * It allows the definition of ids depending on the the squence of EIP currently parsed. 8 | */ 9 | trait NamingStrategy { 10 | 11 | /** 12 | * Identifies the current sequence of EIP. 13 | */ 14 | protected[babel] var routeId: Option[String] = None 15 | 16 | /** 17 | * Defines how Babel tanslates an EIP to its id, if this is the case. 18 | * @param stepDefinition the pattern for which an id is requested. 19 | * @return None if Babel should not provide an id for this pattern, Some id otherwise. 20 | */ 21 | def name(stepDefinition: StepDefinition): Option[String] 22 | 23 | /** 24 | * Used when parsing a new sequence of EIP. 25 | * Helpful if your naming index the pattern with their position in the sequence. 26 | */ 27 | protected[babel] def newRoute(): Unit 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/AggregationDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | /** 12 | * The base trait for all declaration of an aggregator. 13 | * Each DSL (Babel Camel, Babel Fish) need to create their own aggregation declaration with this trait. 14 | * @tparam I the message body type before the aggregation. 15 | * @tparam O the message body type after the aggregation. 16 | */ 17 | trait AggregationConfiguration[I, O] 18 | 19 | /** 20 | * The definition a message filtering in a route. 21 | * @param configuration something the configure the aggregation. 22 | * @tparam I the body type of the input message. 23 | * @tparam O the body type after the aggregation. 24 | */ 25 | case class AggregationDefinition[I, O](configuration: AggregationConfiguration[I, O]) extends StepDefinition 26 | 27 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/BaseDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | import scala.collection.immutable 12 | 13 | /* 14 | * The base classes for a route definition 15 | */ 16 | 17 | /** 18 | * A RouteDefinition contains the definition of the DSL after it has been build. 19 | * @param from the beginning of the route. 20 | */ 21 | case class RouteDefinition(from: FromDefinition) 22 | 23 | /* 24 | * The definitions of some basic blocks (EIP, etc ...) 25 | */ 26 | 27 | /** 28 | * The definition of a sink in the route. 29 | * @param sink the sink itself. 30 | */ 31 | case class EndpointDefinition[I, O](sink: Sink[I, O], requestReply: Option[Boolean] = None) extends StepDefinition 32 | 33 | /** 34 | * The definition of a multicast. A multicast routes the same message to multiple endpoints (sink). 35 | * @param sinks the endpoints. 36 | * @tparam I the body type of the input message. 37 | */ 38 | case class MulticastDefinition[I](sinks: immutable.Seq[Sink[I, _]]) extends StepDefinition 39 | 40 | /** 41 | * The definition of a body message conversion. 42 | * @param outClass the new type of the body message. 43 | */ 44 | case class BodyConvertorDefinition[I, O](inClass: Class[I], outClass: Class[O]) extends StepDefinition 45 | 46 | /** 47 | * The definition of a body type validation. 48 | * @param outClass the required type. 49 | */ 50 | case class BodyTypeValidationDefinition[I, O](inClass: Class[I], outClass: Class[O]) extends StepDefinition 51 | 52 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/ChoiceDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | import scala.collection.immutable 12 | 13 | /* 14 | * Definitions objects that define the "choice" in the DSL 15 | */ 16 | 17 | /** 18 | * The definition of the "choice" block in the DSL. 19 | */ 20 | case class ChoiceDefinition[I]() extends ScopeDefinition[WhenDefinition[I]] { 21 | 22 | /** 23 | * @see WhenDefinition 24 | * @return a list of subroutes 25 | */ 26 | var otherwise: Option[OtherwiseDefinition] = None 27 | 28 | /** 29 | * A helper method for non-scala language. 30 | * It adds a when definition to this choice definition. 31 | * @param when a When defintion. 32 | */ 33 | def addWhen(when: WhenDefinition[I]): Unit = { 34 | this.scopedSteps = scopedSteps :+ when 35 | } 36 | 37 | override def validate(): immutable.Seq[ValidationError] = { 38 | 39 | // validate the subroutes 40 | val whenErrors = scopedSteps.map(_.validate()).flatten 41 | val otherwiseErrors = otherwise.map(_.validate()).getOrElse(immutable.Seq.empty) 42 | 43 | // validate the children definitions 44 | val errors = super.validate() 45 | 46 | // return all the errors 47 | whenErrors ++ otherwiseErrors ++ errors 48 | } 49 | } 50 | 51 | /** 52 | * This class defines a subroute with a predicate. 53 | * @param predicate an object that defined the predicate. 54 | * @tparam I body type of the message. 55 | */ 56 | class WhenDefinition[I](val predicate: Predicate[I]) extends StepDefinition 57 | 58 | /** 59 | * This class defines a subroute if no other subroutes handle the message. 60 | */ 61 | class OtherwiseDefinition extends StepDefinition -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/FilterDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | /** 12 | * The definition of filtering message in a route. 13 | * @param predicate the condition used for the filtering. 14 | * @tparam I the body type. 15 | */ 16 | case class FilterDefinition[I](predicate: Predicate[I]) extends StepDefinition 17 | 18 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/FromDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | // TODO will be fixed in 2.12 https://issues.scala-lang.org/browse/SI-6541 12 | 13 | import scala.language.existentials 14 | 15 | /** 16 | * The FromDefinition define the start of the route. 17 | * @param outClass The type of object generated by the source. 18 | * @param source The source (endpoint) generating the message. 19 | */ 20 | case class FromDefinition(outClass: Class[_], source: Source[_]) extends StepDefinition 21 | 22 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/Model.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | import scala.reflect.ClassTag 12 | 13 | /** 14 | * The source of a route. 15 | * @tparam O 16 | */ 17 | trait Source[+O] 18 | 19 | /** 20 | * The destination of a route. 21 | * @tparam I 22 | * @tparam O 23 | */ 24 | trait Sink[-I, +O] 25 | 26 | /** 27 | * The base case for babel predicate. 28 | * @tparam I the input type. 29 | */ 30 | trait Predicate[-I] extends Expression[I, Boolean] 31 | 32 | /** 33 | * The base class for babel expression. 34 | * @tparam I the input type. 35 | * @tparam O the output type. 36 | */ 37 | trait Expression[-I, +O] 38 | 39 | /** 40 | * A message passing through a route. 41 | * It is immutable and all changes create a new message. 42 | * @tparam T the type of the body. 43 | */ 44 | trait Message[+T] { 45 | 46 | /** 47 | * Returns the body message. 48 | */ 49 | def body: Option[T] 50 | 51 | /** 52 | * Returns the body converted to a new type. 53 | * @tparam A the new type. 54 | * @return the converted body. 55 | */ 56 | def bodyAs[A: ClassTag]: Option[A] 57 | 58 | /** 59 | * Changes the body message with a function. 60 | * This method requires a body. 61 | * @param f the function that process the body. 62 | * @tparam O the type taken by the body after the change. 63 | * @return a new message with the new body. 64 | */ 65 | //todo should we manage the potential NPE as body may be null, or let this problem to the user? 66 | def withBody[O: ClassTag](f: (T => O)): Message[O] 67 | 68 | /** 69 | * Changes the body message with a function. 70 | * This method let you handle the case when the body don't exist. 71 | * @param f the function that process the body. 72 | * @tparam O the type taken by the body after the change. 73 | * @return a new message with the new body. 74 | */ 75 | def withOptionalBody[O: ClassTag](f: (Option[T] => Option[O])): Message[O] 76 | 77 | /** 78 | * Returns an immutable Map of all headers in this message. 79 | * @return an immutable Map with all the headers. 80 | */ 81 | def headers: Map[String, Any] 82 | 83 | /** 84 | * Creates or updates a header in the message. 85 | * @param key the key. 86 | * @param value the value. 87 | * @return a new Message with the new header. 88 | */ 89 | def withHeader(key: String, value: Any): Message[T] 90 | 91 | /** 92 | * Changes the message headers with a function. 93 | * @param f a function processing the headers of the message. 94 | * @return a new Message with modified headers. 95 | */ 96 | def withHeaders(f: (Map[String, Any] => Map[String, Any])): Message[T] 97 | } -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/ScopeDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | import scala.collection.immutable 12 | 13 | /** 14 | * defines an EIP which may have several outputs 15 | */ 16 | protected[babel] class ScopeDefinition[D <: StepDefinition] extends StepDefinition { 17 | 18 | /** 19 | * @return a list of subroutes 20 | */ 21 | protected[babel] var scopedSteps: immutable.IndexedSeq[D] = immutable.IndexedSeq.empty 22 | 23 | } 24 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/SplitterDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | /** 12 | * The definition of message splitter. It split a message in pieces. 13 | * @param expression how the messages are splitted. 14 | * @tparam I the message body type. 15 | * @tparam O the result type after the splitting. 16 | */ 17 | case class SplitterDefinition[I, O](expression: Expression[I, O], stopOnException: Boolean, propagateException: Boolean) extends StepDefinition with SplitConfiguration 18 | 19 | case class SplitReduceDefinition[I, O, G](expression: Expression[I, O], reduce: (G, G) => G, stopOnException: Boolean, propagateException: Boolean) extends StepDefinition with SplitConfiguration { 20 | val internalRouteDefinition = new StepDefinition() {} 21 | 22 | } 23 | 24 | case class SplitFoldDefinition[I, O, G, H](expression: Expression[I, O], seed: H, fold: (H, G) => H, stopOnException: Boolean, propagateException: Boolean) extends StepDefinition with SplitConfiguration { 25 | val internalRouteDefinition = new StepDefinition() {} 26 | } 27 | 28 | trait SplitConfiguration { 29 | def stopOnException: Boolean 30 | 31 | def propagateException: Boolean 32 | } 33 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/StepDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | import scala.collection.immutable 12 | 13 | /** 14 | * A StepDefinition is the base for all Definition in the DSL. 15 | * It define only the next node in the DSL. 16 | */ 17 | trait StepDefinition { 18 | 19 | /** 20 | * the next node in the fish. 21 | */ 22 | protected[babel] var next: Option[StepDefinition] = None 23 | 24 | /** 25 | * meta information such as uuid, description. 26 | * potentially provided by other systems. 27 | */ 28 | protected[babel] var metaInformation: immutable.Map[String, Any] = immutable.Map.empty[String, Any] 29 | 30 | /** 31 | * Validates the definition after the declaration in the fish. 32 | * @return a list of errors. Each error contains an error message and the invalid definition. 33 | */ 34 | protected[babel] def validate(): immutable.Seq[ValidationError] = { 35 | 36 | var errors = immutable.Seq.empty[ValidationError] 37 | 38 | // commons validation 39 | val endpointError: immutable.Seq[ValidationError] = (this, next) match { 40 | // a from definition should not end a route 41 | case (FromDefinition(_, _), None) => immutable.Seq(ValidationError("a route or subroute may not end using a from statement", Some(this))) 42 | //a from definition should not follow another definition 43 | case (_, Some(from @ FromDefinition(_, _))) => immutable.Seq(ValidationError("a from may only start a route", Some(from))) 44 | // otherwise, everything is currently valid 45 | case (_, _) => immutable.Seq.empty 46 | } 47 | 48 | errors = endpointError ++ errors 49 | 50 | // children validation 51 | val childrenErrors = next.map(_.validate()).getOrElse(immutable.Seq.empty) 52 | 53 | errors = childrenErrors ++ errors 54 | 55 | errors 56 | } 57 | } 58 | 59 | /** 60 | * A ValidationError is an error found during the validation phase of the DSL. 61 | * @param errorMessage the error message 62 | * @param definition the definition with an error 63 | */ 64 | case class ValidationError(errorMessage: String, definition: Option[StepDefinition] = None) 65 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/model/TransformerDefinition.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.model 10 | 11 | /** 12 | * The definition of some message transformation. 13 | * @param expression how the message is transformed. 14 | * @tparam I the type of the body. 15 | * @tparam O the type of the body after transformation. 16 | */ 17 | case class TransformerDefinition[I, O](expression: Expression[I, O]) extends StepDefinition 18 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/parsing/Parser.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.parsing 10 | 11 | import io.xtech.babel.fish.model.StepDefinition 12 | 13 | import scala.annotation.tailrec 14 | import scala.collection.immutable 15 | 16 | case class StepInformation[B](step: StepDefinition, previousStepHelper: Any)(implicit val buildHelper: B) 17 | 18 | /** 19 | * base trait for Parsing objects. 20 | * Enforces parsing objects to define one sequence of each possible parsing definition. 21 | * @tparam T 22 | */ 23 | trait Parsing[T] { 24 | type Process = PartialFunction[StepInformation[T], Any] 25 | 26 | //any for last reduced 27 | protected def steps: immutable.Seq[Process] 28 | } 29 | 30 | /** 31 | * base trait for DSL parsers (CamelDSL and SpringIntegrationDSL). 32 | * Provides a method which recursively parses an EIP definition and its children. 33 | * @tparam B 34 | */ 35 | 36 | trait StepProcessor[B] extends Parsing[B] { 37 | 38 | private[this] lazy val parse: Function1[StepInformation[B], Option[Any]] = steps.reduce(_ orElse _).lift 39 | 40 | /** 41 | * Processes each step recursively (but the from, managed by the process method. 42 | * Uses the aggregated parsing method which, for each possible keyword, create the required Mediation engine instance. 43 | * @param info containing the informations of the current step. 44 | * @return the info updated with the next step if any, otherwise the info as processed, to get its RouteBuilder. 45 | * @see CamelDSL.process 46 | */ 47 | 48 | @tailrec 49 | protected[babel] final def processSteps(info: StepInformation[B]): Unit = { 50 | val processed = parse(info).getOrElse(throw new ParsingException.UnknownStepException(info.step.toString)) //todo add step.toString for better comprehension) 51 | info.step.next match { 52 | case Some(next) => { 53 | processSteps(StepInformation(next, processed)(info.buildHelper)) 54 | } 55 | case s => 56 | } 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /babel-fish/src/main/scala/io/xtech/babel/fish/parsing/ParsingException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish.parsing 10 | 11 | object ParsingException { 12 | 13 | /** 14 | * An exception thrown when an unknown step (definition) is found in the Babel fish DSL. 15 | * @param step the unknown step 16 | */ 17 | class UnknownStepException(step: String) extends Exception(s"The step '$step' has not been successfully parsed.") 18 | 19 | } 20 | -------------------------------------------------------------------------------- /babel-fish/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | # All rights reserved. 5 | # 6 | # ================================================================================== 7 | # 8 | 9 | # 10 | # The logging properties used for eclipse testing, We want to see debug output on the console. 11 | # 12 | log4j.rootLogger=INFO, out 13 | 14 | # uncomment the following line to turn on Camel debugging 15 | #log4j.logger.org.apache.camel=DEBUG 16 | 17 | # uncomment the following line to turn on ActiveMQ debugging 18 | #log4j.logger.org.apache.activemq=DEBUG 19 | 20 | log4j.logger.org.springframework=WARN 21 | 22 | 23 | # CONSOLE appender not used by default 24 | log4j.appender.out=org.apache.log4j.ConsoleAppender 25 | log4j.appender.out.layout=org.apache.log4j.PatternLayout 26 | log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n 27 | #log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -------------------------------------------------------------------------------- /babel-fish/src/test/scala/io/xtech/babel/fish/AggregateDSLSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish 10 | 11 | import io.xtech.babel.fish.model._ 12 | import org.specs2.matcher.MatchResult 13 | import org.specs2.mutable.SpecificationWithJUnit 14 | 15 | class AggregateDSLSpec extends SpecificationWithJUnit { 16 | sequential 17 | 18 | "aggregate keyword" should { 19 | "create a route definition with a route containing an aggregation" in { 20 | import io.xtech.babel.fish.Test._ 21 | 22 | case class AP[I, O](func: (I => O)) extends AggregationConfiguration[I, O] 23 | 24 | // create a route 25 | val definitions = new DSL() { 26 | from("direct:input").as[String].aggregate(AP((s: String) => "s")).to("mock:output") 27 | }.build() 28 | 29 | // tests the definition generated from the DSL 30 | definitions.headOption.map(_.from.source.uri) mustEqual Some("direct:input") 31 | 32 | val bodyConvStep = for { 33 | s <- definitions.headOption 34 | step <- s.from.next 35 | } yield step 36 | 37 | bodyConvStep must beSome.like[MatchResult[Any]] { 38 | case step: BodyConvertorDefinition[_, _] => { 39 | step.outClass mustEqual classOf[String] 40 | } 41 | } 42 | 43 | val aggregatorStep = for { previous <- bodyConvStep; step <- previous.next } yield step 44 | aggregatorStep must beSome.like[MatchResult[Any]] { 45 | case step: AggregationDefinition[_, _] => 46 | step.configuration must haveClass[AP[String, String]] 47 | } 48 | 49 | val endpointStep = for { previous <- aggregatorStep; step <- previous.next } yield step 50 | endpointStep must beSome.like[MatchResult[Any]] { 51 | case step: EndpointDefinition[_, _] => { 52 | step.sink.uri mustEqual "mock:output" 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /babel-fish/src/test/scala/io/xtech/babel/fish/Test.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | package io.xtech.babel.fish 10 | 11 | import io.xtech.babel.fish.model.{ Sink, Source } 12 | 13 | import scala.collection.immutable 14 | import scala.language.implicitConversions 15 | 16 | /** 17 | * This class defines what is a source 18 | * @param uri a uri 19 | * @tparam O The type of Object the source generates. 20 | */ 21 | class TestSource[+O](val uri: String) extends Source[O] 22 | 23 | /** 24 | * This class defines what is a sink 25 | * @param uri a uri 26 | * @tparam I The type of Object the sink accepts. 27 | * @tparam O The type of Object the sink generates. 28 | */ 29 | class TestSink[-I, +O](val uri: String) extends Sink[I, O] 30 | 31 | /** 32 | * It defines the implicits that make the fish works. 33 | */ 34 | object Test { 35 | 36 | implicit def stringSource(uri: String) = new TestSource(uri) 37 | 38 | implicit def seqStringSink(uris: Seq[String]) = immutable.Seq(uris.map(new TestSink(_)): _*) 39 | 40 | implicit def stringSink(uri: String) = new TestSink(uri) 41 | 42 | implicit def testSource(source: Source[_]): TestSource[_] = { 43 | 44 | source match { 45 | case testSource: TestSource[_] => { 46 | testSource 47 | } 48 | } 49 | } 50 | 51 | implicit def testSink(sink: Sink[_, _]): TestSink[_, _] = { 52 | 53 | sink match { 54 | case testSink: TestSink[_, _] => { 55 | testSink 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | 2 | organization := "io.xtech.babel" 3 | 4 | name := "babel" 5 | 6 | scalaVersion := "2.11.5" 7 | 8 | crossScalaVersions := Seq("2.10.5", "2.11.6") 9 | -------------------------------------------------------------------------------- /notes/0.6.0.markdown: -------------------------------------------------------------------------------- 1 | First open source version 2 | ========================= 3 | 4 | The initial open source release of Babel essentially presents a set of keyword to be used with Apache Camel. It also provides a core module (Babel fish) in order to implement other DSL. 5 | 6 | 7 | Keywords 8 | -------- 9 | 10 | - Basics 11 | - sources and sinks (from, to, sub) 12 | - route hooks (routeId, onStart, onInit, ...) 13 | - exchange hooks (onExchangeDone, ...) 14 | - logging (log) 15 | - Typing (requireAs, marshal, ...) 16 | - Routing (choice, multicast, recipientList, filter, aggregate, split, vaidate) 17 | - Transformation (enrich, pollEnrich, process, resequence, sort, bean) 18 | - Error handling (handle, on[Throwable], continued, deadletter, loggingErrorHandler, defaultErrorHandler) 19 | 20 | 21 | Mock extension 22 | -------------- 23 | 24 | - Define a subset DSL (Mock) for Babel Camel which may be mix in RouteBuilder to add functionnalities 25 | 26 | 27 | Feature 28 | ------- 29 | 30 | - Integration with the legacy Apache Camel context (RouteBuilder) 31 | - Integration with the Camel Spring context (SpringRouteBuilder) 32 | 33 | Improvement 34 | ----------- 35 | 36 | - Improve the support of scala types (scala.Int, scala.Byte, etc...) 37 | 38 | See the project [readme](https://github.com/crossing-tech/babel) for more information. 39 | -------------------------------------------------------------------------------- /notes/0.7.0.markdown: -------------------------------------------------------------------------------- 1 | Second open source version 2 | ========================== 3 | 4 | Babel has now been used to address several use cases and got improved. Those projects should be put in production with the present released version of Babel. 5 | 6 | Additions 7 | --------- 8 | 9 | - the throttler keyword is added 10 | - Naming strategies may be set to define default ids 11 | 12 | Improvements 13 | ------------ 14 | 15 | - the splitReduceBody and the splitFoldBody keywords let you define how to split, transform and aggregate with a leading API. 16 | - the enrich keyword may take an aggregation configuration argument. 17 | - noAutoStartup becomes autoStartup and takes a parameter. 18 | - Camel exchange may be reached through the CamelMessage (in process method argument). 19 | 20 | 21 | Bug fix 22 | ------- 23 | 24 | - Error handling may be inherited, taking advantage of the elimination of the sub keyword. 25 | 26 | 27 | Deletion 28 | -------- 29 | 30 | - the sub keyword is removed. Concerning error handling, it is replaced by the handlingRoute. 31 | 32 | See the project [readme](https://github.com/crossing-tech/babel) for more information. 33 | -------------------------------------------------------------------------------- /notes/about.markdown: -------------------------------------------------------------------------------- 1 | [Babel](http://crossing-tech.github.io/babel) provides elegant DSL for integration. An implementation exists for Apache Camel. 2 | 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 12 | 4.0.0 13 | 14 | io.xtech.babel 15 | babel 16 | 0.7.0 17 | 18 | 21 | 22 | pom 23 | 24 | Babel :: Main 25 | 26 | 27 | babel-fish 28 | babel-camel 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/Build.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | 10 | import com.typesafe.sbt.SbtScalariform 11 | import com.typesafe.sbt.SbtScalariform.ScalariformKeys 12 | import com.typesafe.sbt.osgi.SbtOsgi 13 | import com.typesafe.sbt.pgp.PgpKeys 14 | import org.scoverage.coveralls.CoverallsPlugin.coverallsSettings 15 | import sbt.Keys._ 16 | import sbt._ 17 | import sbtrelease.ReleasePlugin.{ReleaseKeys, releaseSettings} 18 | import sbtrelease.Version 19 | 20 | object Build extends Build { 21 | 22 | val artifactVersion = "0.8.0" 23 | 24 | lazy val basicSettings = Defaults.defaultSettings ++ Publish.settings ++ coverallsSettings ++ releaseSettings ++ Seq( 25 | version := artifactVersion, 26 | ReleaseKeys.crossBuild := true, 27 | ReleaseKeys.versionBump := Version.Bump.Minor, 28 | ReleaseKeys.publishArtifactsAction := PgpKeys.publishSigned.value 29 | ) 30 | 31 | lazy val defaultSettings = basicSettings ++ formatSettings ++ SbtOsgi.osgiSettings ++ Seq( 32 | fork in test := true 33 | ) 34 | 35 | lazy val root = Project(id = "babel", 36 | base = file("."), 37 | settings = basicSettings ++ Seq( 38 | publishArtifact in(Compile, packageBin) := false, 39 | publishArtifact in(Compile, packageSrc) := false, 40 | publishArtifact in(Compile, packageDoc) := false 41 | ) 42 | ) aggregate(babelfish, babelcamelcore, babelcamelmock) 43 | 44 | lazy val babelfish = Project(id = "babel-fish", 45 | base = file("babel-fish"), 46 | settings = defaultSettings ++ Dependencies.babelFish 47 | ) 48 | 49 | //allows you to define a camelVersion by prompting "set camelVersion=2.10.4" for example. 50 | lazy val camelVersion = SettingKey[String]("x-camel-version") 51 | 52 | lazy val babelcamelcore = Project(id = "babel-camel-core", 53 | base = file("babel-camel/babel-camel-core"), 54 | settings = defaultSettings ++ Dependencies.babelCamelCore++ Seq( 55 | publishArtifact in(Test, packageBin) := true 56 | ) 57 | ).dependsOn(babelfish, babelcamelmock) 58 | 59 | 60 | lazy val babelcamelmock = Project(id = "babel-camel-mock", 61 | base = file("babel-camel/babel-camel-mock"), 62 | settings = defaultSettings ++ Dependencies.babelCamelMock 63 | ).dependsOn(babelfish) 64 | 65 | 66 | 67 | //reformatting enforced for compile phase 68 | lazy val formatSettings = SbtScalariform.scalariformSettings ++ Seq( 69 | ScalariformKeys.preferences in Compile := Formatting.formattingPreferences, 70 | ScalariformKeys.preferences in Test := Formatting.formattingPreferences 71 | ) 72 | 73 | 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /project/Dependencies.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | import com.typesafe.sbt.osgi.OsgiKeys 10 | import sbt._ 11 | import sbt.Keys._ 12 | 13 | object Dependencies { 14 | 15 | 16 | private val testScope = "test" 17 | private val optionalScope = "optional" 18 | private val camelModulePrefix = s"camel" 19 | private val camelGroupId = "org.apache.camel" 20 | private val snapshotSuffix = "-SNAPSHOT" 21 | 22 | lazy val babelFish = Seq(libraryDependencies ++= test, OsgiKeys.exportPackage := Seq("io.xtech.babel.fish.*")) 23 | 24 | lazy val babelCamelMock = Seq( 25 | libraryDependencies ++= Seq(camelCore(fixedCamelVersion)) ++ test, 26 | OsgiKeys.exportPackage := Seq("io.xtech.babel.camel.mock") 27 | ) 28 | 29 | lazy val babelCamelCore = camelDependencies ++ camelTestsDependencies ++ Seq( 30 | OsgiKeys.exportPackage := Seq("io.xtech.babel.camel.*") 31 | ) 32 | 33 | private[this] val fixedCamelVersion = "2.15.0" 34 | 35 | private[this] lazy val camelDependencies = Seq( 36 | Build.camelVersion := fixedCamelVersion, 37 | version <<= (version, Build.camelVersion) { parseCamelVersion }, 38 | //libraryDependencies ++= Seq("com.novocode" % "junit-interface" % "0.8" % "test->default"), 39 | libraryDependencies <++= (Build.camelVersion) { (dv) => 40 | test ++ camel(dv) ++ Seq(csvForTest, xomForTest) 41 | } 42 | ) 43 | 44 | private[this] def parseCamelVersion(babel: String, camel: String): String = { 45 | val camelVersion = if (camel != fixedCamelVersion) { 46 | "-camel-" + camel.split("\\.").take(2).mkString(".") 47 | }else{ 48 | "" 49 | } 50 | babel.replace(snapshotSuffix,"") + camelVersion + {if (babel.endsWith(snapshotSuffix)) {snapshotSuffix} else {""}} 51 | } 52 | 53 | private[this] lazy val camelTestsDependencies = Seq( 54 | libraryDependencies <++= (Build.camelVersion) { (dv) => 55 | Seq(cglib, h2, slf4j) ++ Seq("io.xtech.babel" %% "babel-camel-mock" % Build.artifactVersion exclude("org.apache.camel", "camel-core")) 56 | } 57 | ) 58 | 59 | private[this] val camelCore = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-core" % camelVersion 60 | private[this] val camelXmlJson = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-xmljson" % camelVersion % testScope 61 | private[this] val camelCsv = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-csv" % camelVersion % testScope 62 | private[this] val camelSql = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-sql" % camelVersion % testScope 63 | private[this] val camelSpring = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-spring" % camelVersion % optionalScope 64 | private[this] val camelScala = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-scala" % camelVersion % optionalScope 65 | private[this] val camelQuartz = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-quartz" % camelVersion % optionalScope 66 | private[this] val camelTest = (camelVersion: String) => camelGroupId% s"$camelModulePrefix-test" % camelVersion % testScope 67 | private[this] val csvForTest = "org.apache.commons" % "commons-csv" % "1.1" % testScope 68 | private[this] val xomForTest = "xom" % "xom" % "1.2.5" % testScope 69 | 70 | private[this] def camel(camelVersion: String) = Seq(camelCore, camelXmlJson, camelCsv, camelSql, 71 | camelSpring, camelScala, camelQuartz, camelTest).map(x => (x(camelVersion))) 72 | 73 | private[this] val commoncsv = "org.apache.servicemix.bundles" % "org.apache.servicemix.bundles.commons-csv" % "1.0-r706900_3" % testScope 74 | 75 | 76 | 77 | private[this] val cglib = "cglib" % "cglib-nodep" % "2.2" % testScope 78 | private[this] val h2 = "com.h2database" % "h2" % "1.3.174" % testScope 79 | 80 | 81 | private[this] val specs2 = "org.specs2" %% "specs2" % "2.4.1" % testScope 82 | private[this] val junit = "junit" % "junit" % "4.11" % testScope 83 | 84 | private[this] val test = Seq(junit, specs2) 85 | 86 | private[this] val slf4j = "org.slf4j" % "slf4j-log4j12" % "1.7.3" 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /project/Formatting.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | import scalariform.formatter.preferences._ 10 | 11 | object Formatting{ 12 | 13 | def formattingPreferences: FormattingPreferences = FormattingPreferences() 14 | .setPreference(AlignSingleLineCaseStatements, true) 15 | .setPreference(DoubleIndentClassDeclaration, true) 16 | .setPreference(PreserveDanglingCloseParenthesis, true) 17 | .setPreference(AlignParameters, true) 18 | .setPreference(AlignSingleLineCaseStatements, true) 19 | .setPreference(CompactControlReadability, true) 20 | .setPreference(CompactStringConcatenation, false) 21 | .setPreference(DoubleIndentClassDeclaration, true) 22 | .setPreference(FormatXml, true) 23 | .setPreference(IndentLocalDefs, false) 24 | .setPreference(IndentPackageBlocks, true) 25 | .setPreference(IndentSpaces, 2) 26 | .setPreference(IndentWithTabs, false) 27 | .setPreference(MultilineScaladocCommentsStartOnFirstLine, false) 28 | .setPreference(PreserveDanglingCloseParenthesis, true) 29 | .setPreference(PlaceScaladocAsterisksBeneathSecondAsterisk, true) 30 | .setPreference(PreserveSpaceBeforeArguments, false) 31 | .setPreference(RewriteArrowSymbols, false) 32 | .setPreference(SpaceBeforeColon, false) 33 | .setPreference(SpaceInsideBrackets, false) 34 | .setPreference(SpaceInsideParentheses, false) 35 | .setPreference(SpacesWithinPatternBinders, true) 36 | } -------------------------------------------------------------------------------- /project/Publish.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2010-2014 Crossing-Tech SA, EPFL QI-J, CH-1015 Lausanne, Switzerland. 4 | * All rights reserved. 5 | * 6 | * ================================================================================== 7 | */ 8 | 9 | import sbt.Keys._ 10 | import sbt._ 11 | 12 | object Publish { 13 | 14 | lazy val settings = Seq( 15 | publishMavenStyle := true, 16 | publishArtifact in Test := false, 17 | pomIncludeRepository := { _ => false }, 18 | publishTo := { 19 | val nexus = "https://oss.sonatype.org/" 20 | if (isSnapshot.value) 21 | Some("snapshots" at nexus + "content/repositories/snapshots") 22 | else 23 | Some("releases" at nexus + "service/local/staging/deploy/maven2") 24 | }, 25 | pomExtra := (2014 26 | http://www.crossing-tech.com 27 | 28 | 29 | Apache 2 30 | http://www.apache.org/licenses/LICENSE-2.0.txt 31 | repo 32 | 33 | 34 | 35 | https://github.com/Crossing-Tech/babel.git 36 | scm:git:git@github.com:Crossing-Tech/babel.git 37 | 38 | 39 | 40 | chpache 41 | Christophe Pache 42 | https://twitter.com/chpache 43 | 44 | 45 | leifh 46 | Leif Hallgren 47 | https://twitter.com/lhallgren 48 | 49 | ) 50 | ) 51 | } -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | 2 | resolvers += Classpaths.sbtPluginReleases 3 | 4 | resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/" 5 | 6 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.0.4") 7 | 8 | addSbtPlugin("org.scoverage" %% "sbt-coveralls" % "0.99.0") 9 | 10 | addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "1.0.3") 11 | 12 | addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0") 13 | 14 | addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.7.0") 15 | 16 | addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3") 17 | 18 | addSbtPlugin("com.github.gseitz" % "sbt-release" % "0.8.5") 19 | -------------------------------------------------------------------------------- /src/main/ls/0.6.json: -------------------------------------------------------------------------------- 1 | { 2 | "organization":"io.xtech.babel", 3 | "name":"babel", 4 | "version":"0.6", 5 | "description":"Babel is an efficient way to write your integration solution. It stands as a generic Domain Specific Language (DSL) especially maid for integration duties.", 6 | "site":"http://crossing-tech.github.io/babel", 7 | "tags":["scala", "camel" , "dsl", "mediation"], 8 | "docs":"http://crossing-tech.github.io/babel", 9 | "licenses": [{ 10 | "name": "Apache 2", 11 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 12 | }], 13 | "resolvers": ["https://oss.sonatype.org/content/repositories/snapshots"], 14 | "dependencies": [{ 15 | "organization":"org.apache.camel", 16 | "name": "camel-core", 17 | "version": "2.10.4" 18 | }], 19 | "scalas": ["2.10.3-4, 2.11.0-2"], 20 | "sbt": false 21 | } -------------------------------------------------------------------------------- /src/main/ls/0.7.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "organization": "io.xtech.babel", 3 | "name": "babel", 4 | "version": "0.7.0", 5 | "description": "Babel is an efficient way to write your integration solution. It stands as a generic Domain Specific Language (DSL) especially maid for integration duties.", 6 | "site": "http://crossing-tech.github.io/babel", 7 | "tags": [ 8 | "scala", 9 | "camel", 10 | "dsl", 11 | "mediation" 12 | ], 13 | "docs": "http://crossing-tech.github.io/babel", 14 | "licenses": [ 15 | { 16 | "name": "Apache 2", 17 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 18 | } 19 | ], 20 | "resolvers": ["https://oss.sonatype.org/content/repositories/snapshots"], 21 | "dependencies": [{ 22 | "organization": "org.apache.camel", 23 | "name": "camel-core", 24 | "versions": [ 25 | "2.12.4", 26 | "2.13.3", 27 | "2.14.2", 28 | "2.15.0" 29 | ] 30 | } 31 | ], 32 | "scalas": [ 33 | "2.10.3-5", 34 | "2.11.0-6" 35 | ], 36 | "sbt": false 37 | } 38 | -------------------------------------------------------------------------------- /src/main/ls/0.8.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "organization": "io.xtech.babel", 3 | "name": "babel", 4 | "version": "0.8.0", 5 | "description": "Babel is an efficient way to write your integration solution. It stands as a generic Domain Specific Language (DSL) especially maid for integration duties.", 6 | "site": "http://crossing-tech.github.io/babel", 7 | "tags": [ 8 | "scala", 9 | "camel", 10 | "dsl", 11 | "mediation" 12 | ], 13 | "docs": "http://crossing-tech.github.io/babel", 14 | "licenses": [ 15 | { 16 | "name": "Apache 2", 17 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 18 | } 19 | ], 20 | "resolvers": ["https://oss.sonatype.org/content/repositories/snapshots"], 21 | "dependencies": [{ 22 | "organization": "org.apache.camel", 23 | "name": "camel-core", 24 | "versions": [ 25 | "2.12.4", 26 | "2.13.3", 27 | "2.14.2", 28 | "2.15.0" 29 | ] 30 | } 31 | ], 32 | "scalas": [ 33 | "2.10.3-5", 34 | "2.11.0-6" 35 | ], 36 | "sbt": false 37 | } 38 | --------------------------------------------------------------------------------