From 5a18d434355d74180a0dfc421934e31817eaf384 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 13 Jan 2016 16:25:24 +0100 Subject: [PATCH] +doc #19429 initial merge of docs-dev and docs --- akka-docs-dev/_sphinx/exts/includecode.py | 145 ---- akka-docs-dev/_sphinx/pygments/setup.py | 19 - .../_sphinx/pygments/styles/__init__.py | 0 .../_sphinx/pygments/styles/simple.py | 58 -- .../static/akka-intellij-code-style.jar | Bin 8587 -> 0 bytes akka-docs-dev/_sphinx/static/akka.png | Bin 10746 -> 0 bytes akka-docs-dev/_sphinx/static/favicon.ico | Bin 26683 -> 0 bytes akka-docs-dev/_sphinx/static/logo.png | Bin 10746 -> 0 bytes akka-docs-dev/_sphinx/themes/akka/layout.html | 371 --------- .../themes/akka/static/akka_full_color.svg | 1 - .../akka/static/akka_icon_full_color.svg | 1 - .../themes/akka/static/akka_icon_reverse.svg | 1 - .../themes/akka/static/akka_reverse.svg | 1 - .../_sphinx/themes/akka/static/base.css | 94 --- .../_sphinx/themes/akka/static/contentsFix.js | 10 - .../_sphinx/themes/akka/static/docs.css | 222 ------ .../themes/akka/static/effects.core.js | 509 ------------- .../themes/akka/static/effects.highlight.js | 48 -- .../_sphinx/themes/akka/static/ga.js | 43 -- .../themes/akka/static/highlightCode.js | 13 - .../_sphinx/themes/akka/static/jquery.js | 4 - .../_sphinx/themes/akka/static/logo-small.png | Bin 946 -> 0 bytes .../_sphinx/themes/akka/static/pdf-icon.png | Bin 15170 -> 0 bytes .../themes/akka/static/pdf-java-icon.png | Bin 18845 -> 0 bytes .../themes/akka/static/pdf-scala-icon.png | Bin 19064 -> 0 bytes .../_sphinx/themes/akka/static/prettify.css | 43 -- .../_sphinx/themes/akka/static/prettify.js | 28 - .../_sphinx/themes/akka/static/scrollTo.js | 9 - .../_sphinx/themes/akka/static/style.css | 629 ---------------- .../_sphinx/themes/akka/static/toc.js | 131 ---- .../_sphinx/themes/akka/static/watermark.png | Bin 2442 -> 0 bytes akka-docs-dev/_sphinx/themes/akka/theme.conf | 6 - akka-docs-dev/build.sbt | 30 - akka-docs-dev/rst/conf.py | 87 --- akka-docs-dev/rst/index.rst | 8 - akka-docs-dev/rst/java.rst | 10 - .../rst/java/code/docs/MigrationsJava.java | 249 ------ akka-docs-dev/rst/scala.rst | 10 - .../scaladsl/HttpServerExampleSpec.scala.orig | 407 ---------- akka-docs-dev/rst/stream-configuration.rst | 7 - .../src/test/resources/application.conf | 1 - .../_sphinx/exts/includecode2.py | 0 akka-docs/rst/conf.py | 2 +- .../rst/general/stream}/stages-overview.rst | 0 .../general/stream/stream-configuration.rst | 7 + .../rst/general/stream}/stream-design.rst | 0 .../rst/images/akka-http-file-listing.png | Bin .../rst/images/asyncBoundary.png | Bin .../rst/images/compose_attributes.png | Bin .../rst/images/compose_composites.png | Bin .../rst/images/compose_graph.png | Bin .../rst/images/compose_graph_flow.png | Bin .../rst/images/compose_graph_partial.png | Bin .../rst/images/compose_graph_shape.png | Bin .../rst/images/compose_mat.png | Bin .../rst/images/compose_nested_flow.png | Bin .../rst/images/compose_nested_flow_opaque.png | Bin .../rst/images/compose_shapes.png | Bin .../rst/images/composition.png | Bin .../rst/images/composition.svg | 0 .../rst/images/graph_stage_chain.png | Bin .../rst/images/graph_stage_chain.svg | 0 .../rst/images/graph_stage_conceptual.png | Bin .../rst/images/graph_stage_conceptual.svg | 0 .../images/graph_stage_detached_tracks_1.png | Bin .../images/graph_stage_detached_tracks_1.svg | 0 .../images/graph_stage_detached_tracks_2.png | Bin .../images/graph_stage_detached_tracks_2.svg | 0 .../rst/images/graph_stage_duplicate.png | Bin .../rst/images/graph_stage_duplicate.svg | 0 .../rst/images/graph_stage_filter.png | Bin .../rst/images/graph_stage_filter.svg | 0 .../rst/images/graph_stage_map.png | Bin .../rst/images/graph_stage_map.svg | 0 .../rst/images/graph_stage_tracks_1.png | Bin .../rst/images/graph_stage_tracks_1.svg | 0 .../rst/images/inport_transitions.png | Bin .../rst/images/outport_transitions.png | Bin .../rst/images/port_transitions.svg | 0 .../rst/images/simple-graph-example.png | Bin .../rst/images/stage_chain.png | Bin .../rst/images/stage_conceptual.png | Bin .../rst/images/stage_doubler.png | Bin .../rst/images/stage_filter.png | Bin .../rst/images/stage_map.png | Bin .../rst/images/stage_msc_absorb_1.png | Bin .../rst/images/stage_msc_absorb_2.png | Bin .../rst/images/stage_msc_buffer.png | Bin .../rst/images/stage_msc_general.png | Bin .../rst/images/stages.svg | 0 .../rst/images/stages_sequence_charts.svg | 0 akka-docs/rst/java.rst | 2 + .../java/code/docs/actor/ActorDocTest.java | 639 ++++++++++++++++ .../docs/actor/FaultHandlingTestJava8.java | 204 +++++ .../docs/actor/InitializationDocTest.java | 67 ++ .../rst/java/code/docs/actor/Messages.java | 149 ++++ .../rst/java/code/docs/actor/MyActor.java | 33 + .../rst/java/code/docs/actor/SampleActor.java | 36 + .../java/code/docs/actor/SampleActorTest.java | 55 ++ .../rst/java/code/docs/actor/fsm/Buncher.java | 136 ++++ .../java/code/docs/actor/fsm/BuncherTest.java | 78 ++ .../rst/java/code/docs/actor/fsm/Events.java | 108 +++ .../java/code/docs/actor/fsm/FSMDocTest.java | 179 +++++ .../japi/FaultHandlingDocSampleJava8.java | 470 ++++++++++++ .../javadsl/HttpClientExampleDocTest.java | 0 .../code/docs/http/javadsl/ModelDocTest.java | 0 .../FormFieldRequestValsExampleTest.java | 0 .../server/HeaderRequestValsExampleTest.java | 0 .../HighLevelServerBindFailureExample.java | 0 .../server/HighLevelServerExample.java | 0 .../server/HttpBasicAuthenticatorExample.java | 0 .../server/HttpServerExampleDocTest.java | 0 .../server/OAuth2AuthenticatorExample.java | 0 .../server/PathDirectiveExampleTest.java | 0 .../javadsl/server/WebsocketCoreExample.java | 0 .../server/WebsocketRoutingExample.java | 0 .../HostDirectivesExamplesTest.java | 0 .../MethodDirectivesExamplesTest.java | 0 .../javadsl/server/testkit/MyAppService.java | 0 .../server/testkit/TestkitExampleTest.java | 0 .../docs/stream/ActorPublisherDocTest.java | 150 ++++ .../docs/stream/ActorSubscriberDocTest.java | 233 ++++++ .../code/docs/stream/BidiFlowDocTest.java | 236 ++++++ .../code/docs/stream/CompositionDocTest.java | 308 ++++++++ .../java/code/docs/stream/FlowDocTest.java | 301 ++++++++ .../code/docs/stream/FlowErrorDocTest.java | 140 ++++ .../code/docs/stream/FlowGraphDocTest.java | 172 +++++ .../docs/stream/FlowParallelismDocTest.java | 146 ++++ .../code/docs/stream/FlowStagesDocTest.java | 256 +++++++ .../code/docs/stream/GraphCyclesDocTest.java | 159 ++++ .../code/docs/stream/GraphStageDocTest.java | 712 ++++++++++++++++++ .../code/docs/stream/IntegrationDocTest.java | 596 +++++++++++++++ .../java/code/docs/stream/MigrationsJava.java | 259 +++++++ .../stream/RateTransformationDocTest.java | 165 ++++ .../docs/stream/ReactiveStreamsDocTest.java | 264 +++++++ .../code/docs/stream/SilenceSystemOut.java | 64 ++ .../docs/stream/StreamBuffersRateDocTest.java | 128 ++++ .../stream/StreamPartialFlowGraphDocTest.java | 176 +++++ .../docs/stream/StreamTestKitDocTest.java | 229 ++++++ .../TwitterStreamQuickstartDocTest.java | 362 +++++++++ .../docs/stream/io/StreamFileDocTest.java | 87 +++ .../code/docs/stream/io/StreamTcpDocTest.java | 184 +++++ .../javadsl/cookbook/RecipeByteStrings.java | 207 +++++ .../stream/javadsl/cookbook/RecipeDigest.java | 105 +++ .../cookbook/RecipeDroppyBroadcast.java | 75 ++ .../javadsl/cookbook/RecipeFlattenList.java | 62 ++ .../cookbook/RecipeGlobalRateLimit.java | 236 ++++++ .../stream/javadsl/cookbook/RecipeHold.java | 154 ++++ .../javadsl/cookbook/RecipeKeepAlive.java | 58 ++ .../cookbook/RecipeLoggingElements.java | 95 +++ .../javadsl/cookbook/RecipeManualTrigger.java | 153 ++++ .../javadsl/cookbook/RecipeMissedTicks.java | 97 +++ .../cookbook/RecipeMultiGroupByTest.java | 154 ++++ .../javadsl/cookbook/RecipeParseLines.java | 59 ++ .../cookbook/RecipeReduceByKeyTest.java | 124 +++ .../javadsl/cookbook/RecipeSimpleDrop.java | 78 ++ .../stream/javadsl/cookbook/RecipeTest.java | 40 + .../javadsl/cookbook/RecipeToStrict.java | 57 ++ .../javadsl/cookbook/RecipeWorkerPool.java | 87 +++ .../rst/java/code/docs/util/SocketUtils.java | 31 + .../http/client-side/connection-level.rst | 0 .../rst/java/http/client-side/host-level.rst | 0 .../java/http/client-side/https-support.rst | 0 .../rst/java/http/client-side/index.rst | 0 .../java/http/client-side/request-level.rst | 0 .../http/client-side/websocket-support.rst | 0 .../rst/java/http/configuration.rst | 0 .../rst/java/http/http-model.rst | 0 .../rst/java/http/index.rst | 0 .../host-directives/extractHost.rst | 0 .../directives/host-directives/host.rst | 0 .../directives/host-directives/index.rst | 0 .../http/routing-dsl/directives/index.rst | 0 .../directives/method-directives/delete.rst | 0 .../method-directives/extractMethod.rst | 0 .../directives/method-directives/get.rst | 0 .../directives/method-directives/head.rst | 0 .../directives/method-directives/index.rst | 0 .../directives/method-directives/method.rst | 0 .../directives/method-directives/options.rst | 0 .../overrideMethodWithParameter.rst | 0 .../directives/method-directives/patch.rst | 0 .../directives/method-directives/post.rst | 0 .../directives/method-directives/put.rst | 0 .../directives/path-directives.rst | 0 .../rst/java/http/routing-dsl/handlers.rst | 22 +- .../rst/java/http/routing-dsl/index.rst | 0 .../java/http/routing-dsl/json-support.rst | 0 .../rst/java/http/routing-dsl/marshalling.rst | 0 .../rst/java/http/routing-dsl/overview.rst | 2 +- .../request-vals/form-field-request-vals.rst | 0 .../request-vals/header-request-vals.rst | 0 .../request-vals/http-basic-authenticator.rst | 0 .../http/routing-dsl/request-vals/index.rst | 0 .../request-vals/oauth2-authenticator.rst | 0 .../rst/java/http/routing-dsl/routes.rst | 0 .../rst/java/http/routing-dsl/testkit.rst | 0 .../server-side/low-level-server-side-api.rst | 2 +- .../http/server-side/websocket-support.rst | 0 .../rst/java/stream/index.rst | 6 +- .../stream}/migration-guide-1.0-2.x-java.rst | 34 +- .../rst/java/stream}/stream-composition.rst | 50 +- .../rst/java/stream}/stream-cookbook.rst | 58 +- .../rst/java/stream}/stream-customize.rst | 42 +- .../rst/java/stream}/stream-error.rst | 14 +- .../java/stream}/stream-flows-and-basics.rst | 20 +- .../rst/java/stream}/stream-graphs.rst | 40 +- .../rst/java/stream}/stream-integrations.rst | 54 +- .../rst/java/stream}/stream-introduction.rst | 0 .../rst/java/stream}/stream-io.rst | 12 +- .../rst/java/stream}/stream-parallelism.rst | 8 +- .../rst/java/stream}/stream-quickstart.rst | 26 +- .../rst/java/stream}/stream-rate.rst | 28 +- .../rst/java/stream}/stream-testkit.rst | 20 +- .../project/migration-guide-2.3.x-2.4.x.rst | 3 + akka-docs/rst/scala.rst | 2 + .../scala/code/docs/actor/ActorDocSpec.scala | 26 +- .../http/scaladsl/HttpClientExampleSpec.scala | 0 .../http/scaladsl/HttpServerExampleSpec.scala | 0 .../code/docs/http/scaladsl/MarshalSpec.scala | 0 .../code/docs/http/scaladsl/ModelSpec.scala | 0 .../http/scaladsl/SprayJsonExampleSpec.scala | 0 .../docs/http/scaladsl/UnmarshalSpec.scala | 0 .../CaseClassExtractionExamplesSpec.scala | 2 + .../server/DirectiveExamplesSpec.scala | 0 .../server/ExceptionHandlerExamplesSpec.scala | 0 .../server/FileUploadExamplesSpec.scala | 0 .../server/FullTestKitExampleSpec.scala | 0 .../server/RejectionHandlerExamplesSpec.scala | 0 .../http/scaladsl/server/RoutingSpec.scala | 0 .../server/WebsocketExampleSpec.scala | 0 .../BasicDirectivesExamplesSpec.scala | 4 +- .../CodingDirectivesExamplesSpec.scala | 4 +- .../CookieDirectivesExamplesSpec.scala | 4 +- .../CustomDirectivesExamplesSpec.scala | 3 +- .../DebuggingDirectivesExamplesSpec.scala | 4 +- .../ExecutionDirectivesExamplesSpec.scala | 4 +- ...ileAndResourceDirectivesExamplesSpec.scala | 1 + .../FileUploadDirectivesExamplesSpec.scala | 0 .../FormFieldDirectivesExamplesSpec.scala | 4 +- .../FutureDirectivesExamplesSpec.scala | 5 +- .../HeaderDirectivesExamplesSpec.scala | 4 +- .../HostDirectivesExamplesSpec.scala | 4 +- .../MarshallingDirectivesExamplesSpec.scala | 4 +- .../MethodDirectivesExamplesSpec.scala | 4 +- .../MiscDirectivesExamplesSpec.scala | 4 +- .../ParameterDirectivesExamplesSpec.scala | 4 +- .../PathDirectivesExamplesSpec.scala | 4 +- .../RangeDirectivesExamplesSpec.scala | 4 +- .../RespondWithDirectivesExamplesSpec.scala | 4 +- .../RouteDirectivesExamplesSpec.scala | 4 +- .../SchemeDirectivesExamplesSpec.scala | 4 +- .../SecurityDirectivesExamplesSpec.scala | 4 +- .../WebsocketDirectivesExamplesSpec.scala | 1 - .../docs/stream/ActorPublisherDocSpec.scala | 0 .../docs/stream/ActorSubscriberDocSpec.scala | 0 .../code/docs/stream/BidiFlowDocSpec.scala | 0 .../code/docs/stream/CompositionDocSpec.scala | 0 .../scala/code/docs/stream/FlowDocSpec.scala | 0 .../code/docs/stream/FlowErrorDocSpec.scala | 0 .../code/docs/stream/FlowGraphDocSpec.scala | 0 .../docs/stream/FlowParallelismDocSpec.scala | 0 .../code/docs/stream/FlowStagesSpec.scala | 0 .../code/docs/stream/GraphCyclesSpec.scala | 0 .../code/docs/stream/GraphStageDocSpec.scala | 0 .../code/docs/stream/IntegrationDocSpec.scala | 0 .../code/docs/stream}/MigrationsScala.scala | 21 +- .../stream/RateTransformationDocSpec.scala | 0 .../docs/stream/ReactiveStreamsDocSpec.scala | 0 .../docs/stream/StreamBuffersRateSpec.scala | 0 .../StreamPartialFlowGraphDocSpec.scala | 0 .../docs/stream/StreamTestKitDocSpec.scala | 0 .../TwitterStreamQuickstartDocSpec.scala | 0 .../stream/cookbook/RecipeByteStrings.scala | 0 .../cookbook/RecipeCollectingMetrics.scala | 2 +- .../docs/stream/cookbook/RecipeDigest.scala | 0 .../cookbook/RecipeDroppyBroadcast.scala | 0 .../stream/cookbook/RecipeFlattenSeq.scala | 0 .../cookbook/RecipeGlobalRateLimit.scala | 0 .../docs/stream/cookbook/RecipeHold.scala | 0 .../stream/cookbook/RecipeKeepAlive.scala | 0 .../cookbook/RecipeLoggingElements.scala | 0 .../stream/cookbook/RecipeManualTrigger.scala | 0 .../stream/cookbook/RecipeMissedTicks.scala | 0 .../stream/cookbook/RecipeMultiGroupBy.scala | 0 .../stream/cookbook/RecipeParseLines.scala | 0 .../stream/cookbook/RecipeReduceByKey.scala | 0 .../stream/cookbook/RecipeSimpleDrop.scala | 0 .../docs/stream/cookbook/RecipeSpec.scala | 0 .../docs/stream/cookbook/RecipeToStrict.scala | 0 .../stream/cookbook/RecipeWorkerPool.scala | 0 .../docs/stream/io/StreamFileDocSpec.scala | 0 .../docs/stream/io/StreamTcpDocSpec.scala | 0 .../rst/scala/code/docs/utils/TestUtils.scala | 0 .../http/client-side/connection-level.rst | 0 .../rst/scala/http/client-side/host-level.rst | 0 .../scala/http/client-side/https-support.rst | 0 .../rst/scala/http/client-side/index.rst | 0 .../scala/http/client-side/request-level.rst | 0 .../http/client-side/websocket-support.rst | 0 .../rst/scala/http/common/de-coding.rst | 0 .../rst/scala/http/common/http-model.rst | 0 .../rst/scala/http/common/index.rst | 0 .../rst/scala/http/common/json-support.rst | 0 .../rst/scala/http/common/marshalling.rst | 0 .../rst/scala/http/common/unmarshalling.rst | 0 .../rst/scala/http/common/xml-support.rst | 0 .../rst/scala/http/configuration.rst | 0 .../rst/scala/http/index.rst | 0 .../rst/scala/http/introduction.rst | 0 .../scala/http/low-level-server-side-api.rst | 0 .../rst/scala/http/migration-from-spray.rst | 0 .../routing-dsl/case-class-extraction.rst | 0 .../routing-dsl/directives/alphabetically.rst | 0 .../basic-directives/cancelRejection.rst | 0 .../basic-directives/cancelRejections.rst | 0 .../directives/basic-directives/extract.rst | 0 .../extractExecutionContext.rst | 0 .../basic-directives/extractLog.rst | 0 .../basic-directives/extractMaterializer.rst | 0 .../basic-directives/extractRequest.rst | 0 .../extractRequestContext.rst | 0 .../basic-directives/extractSettings.rst | 0 .../basic-directives/extractUnmatchedPath.rst | 0 .../basic-directives/extractUri.rst | 0 .../directives/basic-directives/index.rst | 0 .../basic-directives/mapInnerRoute.rst | 0 .../basic-directives/mapRejections.rst | 0 .../basic-directives/mapRequest.rst | 0 .../basic-directives/mapRequestContext.rst | 0 .../basic-directives/mapResponse.rst | 0 .../basic-directives/mapResponseEntity.rst | 0 .../basic-directives/mapResponseHeaders.rst | 0 .../basic-directives/mapRouteResult.rst | 0 .../basic-directives/mapRouteResultFuture.rst | 0 .../basic-directives/mapRouteResultPF.rst | 0 .../basic-directives/mapRouteResultWith.rst | 0 .../basic-directives/mapRouteResultWithPF.rst | 0 .../basic-directives/mapSettings.rst | 0 .../basic-directives/mapUnmatchedPath.rst | 0 .../directives/basic-directives/pass.rst | 0 .../directives/basic-directives/provide.rst | 0 .../basic-directives/recoverRejections.rst | 0 .../recoverRejectionsWith.rst | 0 .../directives/basic-directives/textract.rst | 0 .../directives/basic-directives/tprovide.rst | 0 .../basic-directives/withExecutionContext.rst | 0 .../directives/basic-directives/withLog.rst | 0 .../basic-directives/withMaterializer.rst | 0 .../basic-directives/withSettings.rst | 0 .../http/routing-dsl/directives/by-trait.rst | 0 .../conditional.rst | 0 .../cache-condition-directives/index.rst | 0 .../coding-directives/decodeRequest.rst | 0 .../coding-directives/decodeRequestWith.rst | 0 .../coding-directives/encodeResponse.rst | 0 .../coding-directives/encodeResponseWith.rst | 0 .../directives/coding-directives/index.rst | 0 .../coding-directives/requestEncodedWith.rst | 0 .../responseEncodingAccepted.rst | 0 .../directives/cookie-directives/cookie.rst | 0 .../cookie-directives/deleteCookie.rst | 0 .../directives/cookie-directives/index.rst | 0 .../cookie-directives/optionalCookie.rst | 0 .../cookie-directives/setCookie.rst | 0 .../directives/custom-directives.rst | 0 .../directives/debugging-directives/index.rst | 0 .../debugging-directives/logRequest.rst | 0 .../debugging-directives/logRequestResult.rst | 0 .../debugging-directives/logResult.rst | 0 .../execution-directives/handleExceptions.rst | 0 .../execution-directives/handleRejections.rst | 0 .../directives/execution-directives/index.rst | 0 .../getFromBrowseableDirectories.rst | 0 .../getFromBrowseableDirectory.rst | 0 .../getFromDirectory.rst | 0 .../getFromFile.rst | 0 .../getFromResource.rst | 0 .../getFromResourceDirectory.rst | 0 .../file-and-resource-directives/index.rst | 0 .../listDirectoryContents.rst | 0 .../file-upload-directives/fileUpload.rst | 0 .../file-upload-directives/index.rst | 0 .../file-upload-directives/uploadedFile.rst | 0 .../form-field-directives/formField.rst | 0 .../form-field-directives/formFields.rst | 0 .../form-field-directives/index.rst | 0 .../completeOrRecoverWith.rst | 0 .../directives/future-directives/index.rst | 0 .../future-directives/onComplete.rst | 0 .../future-directives/onSuccess.rst | 0 .../header-directives/headerValue.rst | 0 .../header-directives/headerValueByName.rst | 0 .../header-directives/headerValueByType.rst | 0 .../header-directives/headerValuePF.rst | 0 .../directives/header-directives/index.rst | 0 .../header-directives/optionalHeaderValue.rst | 0 .../optionalHeaderValueByName.rst | 0 .../optionalHeaderValueByType.rst | 0 .../optionalHeaderValuePF.rst | 0 .../host-directives/extractHost.rst | 0 .../directives/host-directives/host.rst | 0 .../directives/host-directives/index.rst | 0 .../http/routing-dsl/directives/index.rst | 0 .../marshalling-directives/completeWith.rst | 0 .../marshalling-directives/entity.rst | 0 .../marshalling-directives/handleWith.rst | 0 .../marshalling-directives/index.rst | 0 .../directives/method-directives/delete.rst | 0 .../method-directives/extractMethod.rst | 0 .../directives/method-directives/get.rst | 0 .../directives/method-directives/head.rst | 0 .../directives/method-directives/index.rst | 0 .../directives/method-directives/method.rst | 0 .../directives/method-directives/options.rst | 0 .../overrideMethodWithParameter.rst | 0 .../directives/method-directives/patch.rst | 0 .../directives/method-directives/post.rst | 0 .../directives/method-directives/put.rst | 0 .../misc-directives/extractClientIP.rst | 0 .../directives/misc-directives/index.rst | 0 .../misc-directives/rejectEmptyResponse.rst | 0 .../misc-directives/requestEntityEmpty.rst | 0 .../misc-directives/requestEntityPresent.rst | 0 .../selectPreferredLanguage.rst | 0 .../directives/misc-directives/validate.rst | 0 .../directives/parameter-directives/index.rst | 0 .../parameter-directives/parameter.rst | 0 .../parameter-directives/parameterMap.rst | 0 .../parameterMultiMap.rst | 0 .../parameter-directives/parameterSeq.rst | 0 .../parameter-directives/parameters.rst | 0 .../directives/path-directives/index.rst | 0 .../directives/path-directives/path.rst | 0 .../directives/path-directives/pathEnd.rst | 0 .../path-directives/pathEndOrSingleSlash.rst | 0 .../directives/path-directives/pathPrefix.rst | 0 .../path-directives/pathPrefixTest.rst | 0 .../path-directives/pathSingleSlash.rst | 0 .../directives/path-directives/pathSuffix.rst | 0 .../path-directives/pathSuffixTest.rst | 0 .../path-directives/rawPathPrefix.rst | 0 .../path-directives/rawPathPrefixTest.rst | 0 .../redirectToNoTrailingSlashIfPresent.rst | 0 .../redirectToTrailingSlashIfMissing.rst | 0 .../directives/range-directives/index.rst | 0 .../range-directives/withRangeSupport.rst | 0 .../respond-with-directives/index.rst | 0 .../respondWithDefaultHeader.rst | 0 .../respondWithDefaultHeaders.rst | 0 .../respondWithHeader.rst | 0 .../respondWithHeaders.rst | 0 .../directives/route-directives/complete.rst | 0 .../directives/route-directives/failWith.rst | 0 .../directives/route-directives/index.rst | 0 .../directives/route-directives/redirect.rst | 0 .../directives/route-directives/reject.rst | 0 .../scheme-directives/extractScheme.rst | 0 .../directives/scheme-directives/index.rst | 0 .../directives/scheme-directives/scheme.rst | 0 .../security-directives/authenticateBasic.rst | 0 .../authenticateBasicAsync.rst | 0 .../authenticateBasicPF.rst | 0 .../authenticateBasicPFAsync.rst | 0 .../authenticateOAuth2.rst | 0 .../authenticateOAuth2Async.rst | 0 .../authenticateOAuth2PF.rst | 0 .../authenticateOAuth2PFAsync.rst | 0 .../authenticateOrRejectWithChallenge.rst | 0 .../security-directives/authorize.rst | 0 .../extractCredentials.rst | 0 .../directives/security-directives/index.rst | 0 .../handleWebsocketMessages.rst | 0 .../handleWebsocketMessagesForProtocol.rst | 0 .../directives/websocket-directives/index.rst | 0 .../http/routing-dsl/exception-handling.rst | 0 .../rst/scala/http/routing-dsl/index.rst | 0 .../rst/scala/http/routing-dsl/overview.rst | 0 .../scala/http/routing-dsl/path-matchers.rst | 0 .../rst/scala/http/routing-dsl/rejections.rst | 0 .../rst/scala/http/routing-dsl/routes.rst | 0 .../rst/scala/http/routing-dsl/testkit.rst | 0 .../http/routing-dsl/websocket-support.rst | 0 .../rst/scala/stream/index.rst | 6 +- .../stream}/migration-guide-1.0-2.x-scala.rst | 34 +- .../rst/scala/stream}/stream-composition.rst | 48 +- .../rst/scala/stream}/stream-cookbook.rst | 46 +- .../rst/scala/stream}/stream-customize.rst | 44 +- .../rst/scala/stream}/stream-error.rst | 14 +- .../scala/stream}/stream-flows-and-basics.rst | 20 +- .../rst/scala/stream}/stream-graphs.rst | 48 +- .../rst/scala/stream}/stream-integrations.rst | 54 +- .../rst/scala/stream}/stream-introduction.rst | 0 .../rst/scala/stream}/stream-io.rst | 12 +- .../rst/scala/stream}/stream-parallelism.rst | 8 +- .../rst/scala/stream}/stream-quickstart.rst | 26 +- .../rst/scala/stream}/stream-rate.rst | 28 +- .../rst/scala/stream}/stream-testkit.rst | 20 +- akka-docs/src/test/resources/application.conf | 2 + project/AkkaBuild.scala | 10 +- project/Doc.scala | 2 +- 501 files changed, 9876 insertions(+), 3681 deletions(-) delete mode 100644 akka-docs-dev/_sphinx/exts/includecode.py delete mode 100644 akka-docs-dev/_sphinx/pygments/setup.py delete mode 100644 akka-docs-dev/_sphinx/pygments/styles/__init__.py delete mode 100644 akka-docs-dev/_sphinx/pygments/styles/simple.py delete mode 100644 akka-docs-dev/_sphinx/static/akka-intellij-code-style.jar delete mode 100644 akka-docs-dev/_sphinx/static/akka.png delete mode 100644 akka-docs-dev/_sphinx/static/favicon.ico delete mode 100644 akka-docs-dev/_sphinx/static/logo.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/layout.html delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/akka_full_color.svg delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/akka_icon_full_color.svg delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/akka_icon_reverse.svg delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/akka_reverse.svg delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/base.css delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/contentsFix.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/docs.css delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/effects.core.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/effects.highlight.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/ga.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/highlightCode.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/jquery.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/logo-small.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/pdf-icon.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/pdf-java-icon.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/pdf-scala-icon.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/prettify.css delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/prettify.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/scrollTo.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/style.css delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/toc.js delete mode 100644 akka-docs-dev/_sphinx/themes/akka/static/watermark.png delete mode 100644 akka-docs-dev/_sphinx/themes/akka/theme.conf delete mode 100644 akka-docs-dev/build.sbt delete mode 100644 akka-docs-dev/rst/conf.py delete mode 100644 akka-docs-dev/rst/index.rst delete mode 100644 akka-docs-dev/rst/java.rst delete mode 100644 akka-docs-dev/rst/java/code/docs/MigrationsJava.java delete mode 100644 akka-docs-dev/rst/scala.rst delete mode 100644 akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala.orig delete mode 100644 akka-docs-dev/rst/stream-configuration.rst delete mode 100644 akka-docs-dev/src/test/resources/application.conf rename {akka-docs-dev => akka-docs}/_sphinx/exts/includecode2.py (100%) rename {akka-docs-dev/rst => akka-docs/rst/general/stream}/stages-overview.rst (100%) create mode 100644 akka-docs/rst/general/stream/stream-configuration.rst rename {akka-docs-dev/rst => akka-docs/rst/general/stream}/stream-design.rst (100%) rename {akka-docs-dev => akka-docs}/rst/images/akka-http-file-listing.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/asyncBoundary.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_attributes.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_composites.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_graph.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_graph_flow.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_graph_partial.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_graph_shape.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_mat.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_nested_flow.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_nested_flow_opaque.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/compose_shapes.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/composition.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/composition.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_chain.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_chain.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_conceptual.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_conceptual.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_detached_tracks_1.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_detached_tracks_1.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_detached_tracks_2.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_detached_tracks_2.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_duplicate.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_duplicate.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_filter.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_filter.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_map.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_map.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_tracks_1.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/graph_stage_tracks_1.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/inport_transitions.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/outport_transitions.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/port_transitions.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/simple-graph-example.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_chain.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_conceptual.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_doubler.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_filter.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_map.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_msc_absorb_1.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_msc_absorb_2.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_msc_buffer.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stage_msc_general.png (100%) rename {akka-docs-dev => akka-docs}/rst/images/stages.svg (100%) rename {akka-docs-dev => akka-docs}/rst/images/stages_sequence_charts.svg (100%) create mode 100644 akka-docs/rst/java/code/docs/actor/ActorDocTest.java create mode 100644 akka-docs/rst/java/code/docs/actor/FaultHandlingTestJava8.java create mode 100644 akka-docs/rst/java/code/docs/actor/InitializationDocTest.java create mode 100644 akka-docs/rst/java/code/docs/actor/Messages.java create mode 100644 akka-docs/rst/java/code/docs/actor/MyActor.java create mode 100644 akka-docs/rst/java/code/docs/actor/SampleActor.java create mode 100644 akka-docs/rst/java/code/docs/actor/SampleActorTest.java create mode 100644 akka-docs/rst/java/code/docs/actor/fsm/Buncher.java create mode 100644 akka-docs/rst/java/code/docs/actor/fsm/BuncherTest.java create mode 100644 akka-docs/rst/java/code/docs/actor/fsm/Events.java create mode 100644 akka-docs/rst/java/code/docs/actor/fsm/FSMDocTest.java create mode 100644 akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSampleJava8.java rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/HttpClientExampleDocTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/ModelDocTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/HighLevelServerExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/HttpBasicAuthenticatorExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/HttpServerExampleDocTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/OAuth2AuthenticatorExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/PathDirectiveExampleTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/WebsocketCoreExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/WebsocketRoutingExample.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/testkit/MyAppService.java (100%) rename {akka-docs-dev => akka-docs}/rst/java/code/docs/http/javadsl/server/testkit/TestkitExampleTest.java (100%) create mode 100644 akka-docs/rst/java/code/docs/stream/ActorPublisherDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/ActorSubscriberDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/BidiFlowDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/CompositionDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/FlowDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/FlowErrorDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/FlowGraphDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/FlowParallelismDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/FlowStagesDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/GraphCyclesDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/GraphStageDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/IntegrationDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/MigrationsJava.java create mode 100644 akka-docs/rst/java/code/docs/stream/RateTransformationDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/ReactiveStreamsDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/SilenceSystemOut.java create mode 100644 akka-docs/rst/java/code/docs/stream/StreamBuffersRateDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/StreamPartialFlowGraphDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/StreamTestKitDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/TwitterStreamQuickstartDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/io/StreamFileDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/io/StreamTcpDocTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeByteStrings.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDigest.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeFlattenList.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeHold.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeKeepAlive.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMissedTicks.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMultiGroupByTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeParseLines.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeSimpleDrop.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeTest.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeToStrict.java create mode 100644 akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java create mode 100644 akka-docs/rst/java/code/docs/util/SocketUtils.java rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/connection-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/host-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/https-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/request-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/client-side/websocket-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/configuration.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/http-model.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/host-directives/extractHost.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/host-directives/host.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/host-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/delete.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/extractMethod.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/get.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/head.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/method.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/options.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/patch.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/post.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/method-directives/put.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/directives/path-directives.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/handlers.rst (83%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/json-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/marshalling.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/overview.rst (99%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/request-vals/header-request-vals.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/request-vals/http-basic-authenticator.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/request-vals/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/request-vals/oauth2-authenticator.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/routes.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/routing-dsl/testkit.rst (100%) rename {akka-docs-dev => akka-docs}/rst/java/http/server-side/low-level-server-side-api.rst (99%) rename {akka-docs-dev => akka-docs}/rst/java/http/server-side/websocket-support.rst (100%) rename akka-docs-dev/rst/java/stream-index.rst => akka-docs/rst/java/stream/index.rst (74%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/migration-guide-1.0-2.x-java.rst (95%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-composition.rst (86%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-cookbook.rst (83%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-customize.rst (91%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-error.rst (73%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-flows-and-basics.rst (94%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-graphs.rst (87%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-integrations.rst (81%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-introduction.rst (100%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-io.rst (90%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-parallelism.rst (92%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-quickstart.rst (85%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-rate.rst (80%) rename {akka-docs-dev/rst/java => akka-docs/rst/java/stream}/stream-testkit.rst (72%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/HttpClientExampleSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/MarshalSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/ModelSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/SprayJsonExampleSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/UnmarshalSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala (99%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/DirectiveExamplesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/FileUploadExamplesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/FullTestKitExampleSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/RoutingSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/WebsocketExampleSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala (99%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala (98%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala (95%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala (97%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala (95%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala (98%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala (93%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala (98%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala (95%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala (97%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala (98%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala (99%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala (95%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala (92%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala (99%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala (99%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/ActorPublisherDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/ActorSubscriberDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/BidiFlowDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/CompositionDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/FlowDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/FlowErrorDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/FlowGraphDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/FlowParallelismDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/FlowStagesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/GraphCyclesSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/GraphStageDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/IntegrationDocSpec.scala (100%) rename {akka-docs-dev/rst/scala/code/docs => akka-docs/rst/scala/code/docs/stream}/MigrationsScala.scala (94%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/RateTransformationDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/ReactiveStreamsDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/StreamPartialFlowGraphDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/StreamTestKitDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/TwitterStreamQuickstartDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeByteStrings.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala (96%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeDigest.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeDroppyBroadcast.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeFlattenSeq.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeGlobalRateLimit.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeHold.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeLoggingElements.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeManualTrigger.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeMissedTicks.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeMultiGroupBy.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeParseLines.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeReduceByKey.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeSimpleDrop.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeToStrict.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/cookbook/RecipeWorkerPool.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/io/StreamFileDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/code/docs/utils/TestUtils.scala (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/connection-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/host-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/https-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/request-level.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/client-side/websocket-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/de-coding.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/http-model.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/json-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/marshalling.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/unmarshalling.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/common/xml-support.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/configuration.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/introduction.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/low-level-server-side-api.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/migration-from-spray.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/case-class-extraction.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/alphabetically.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejection.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejections.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extract.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractExecutionContext.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractLog.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractMaterializer.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractRequest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractRequestContext.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractSettings.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractUnmatchedPath.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/extractUri.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapInnerRoute.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRejections.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRequest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRequestContext.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapResponse.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseEntity.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseHeaders.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResult.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultFuture.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultPF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWithPF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapSettings.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/mapUnmatchedPath.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/pass.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/provide.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejections.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejectionsWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/textract.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/tprovide.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/withExecutionContext.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/withLog.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/withMaterializer.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/basic-directives/withSettings.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/by-trait.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cache-condition-directives/conditional.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cache-condition-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequestWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponse.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponseWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/requestEncodedWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/coding-directives/responseEncodingAccepted.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cookie-directives/cookie.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cookie-directives/deleteCookie.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cookie-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cookie-directives/optionalCookie.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/cookie-directives/setCookie.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/custom-directives.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/debugging-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/debugging-directives/logRequest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/debugging-directives/logRequestResult.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/debugging-directives/logResult.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/execution-directives/handleExceptions.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/execution-directives/handleRejections.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/execution-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectories.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectory.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromDirectory.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromFile.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResource.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResourceDirectory.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-and-resource-directives/listDirectoryContents.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-upload-directives/fileUpload.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-upload-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/file-upload-directives/uploadedFile.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/form-field-directives/formField.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/form-field-directives/formFields.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/form-field-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/future-directives/completeOrRecoverWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/future-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/future-directives/onComplete.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/future-directives/onSuccess.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/headerValue.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/headerValueByName.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/headerValueByType.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/headerValuePF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValue.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByName.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByType.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValuePF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/host-directives/extractHost.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/host-directives/host.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/host-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/marshalling-directives/completeWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/marshalling-directives/entity.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/marshalling-directives/handleWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/marshalling-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/delete.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/extractMethod.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/get.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/head.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/method.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/options.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/patch.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/post.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/method-directives/put.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/extractClientIP.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/rejectEmptyResponse.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityEmpty.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityPresent.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/selectPreferredLanguage.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/misc-directives/validate.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/parameter.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMap.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMultiMap.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/parameterSeq.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/parameter-directives/parameters.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/path.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathEnd.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathEndOrSingleSlash.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathPrefix.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathPrefixTest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathSingleSlash.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathSuffix.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/pathSuffixTest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefix.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefixTest.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/redirectToNoTrailingSlashIfPresent.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/path-directives/redirectToTrailingSlashIfMissing.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/range-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/range-directives/withRangeSupport.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/respond-with-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeader.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeaders.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeader.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeaders.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/route-directives/complete.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/route-directives/failWith.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/route-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/route-directives/redirect.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/route-directives/reject.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/scheme-directives/extractScheme.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/scheme-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/scheme-directives/scheme.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasic.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicAsync.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPFAsync.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2Async.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PF.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PFAsync.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authenticateOrRejectWithChallenge.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/authorize.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/extractCredentials.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/security-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessages.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessagesForProtocol.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/directives/websocket-directives/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/exception-handling.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/index.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/overview.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/path-matchers.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/rejections.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/routes.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/testkit.rst (100%) rename {akka-docs-dev => akka-docs}/rst/scala/http/routing-dsl/websocket-support.rst (100%) rename akka-docs-dev/rst/scala/stream-index.rst => akka-docs/rst/scala/stream/index.rst (74%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/migration-guide-1.0-2.x-scala.rst (95%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-composition.rst (90%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-cookbook.rst (90%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-customize.rst (93%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-error.rst (82%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-flows-and-basics.rst (96%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-graphs.rst (91%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-integrations.rst (87%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-introduction.rst (100%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-io.rst (93%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-parallelism.rst (94%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-quickstart.rst (89%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-rate.rst (87%) rename {akka-docs-dev/rst/scala => akka-docs/rst/scala/stream}/stream-testkit.rst (83%) create mode 100644 akka-docs/src/test/resources/application.conf diff --git a/akka-docs-dev/_sphinx/exts/includecode.py b/akka-docs-dev/_sphinx/exts/includecode.py deleted file mode 100644 index 6ee9ed3bed..0000000000 --- a/akka-docs-dev/_sphinx/exts/includecode.py +++ /dev/null @@ -1,145 +0,0 @@ -import os -import codecs -from os import path - -from docutils import nodes -from docutils.parsers.rst import Directive, directives - -class IncludeCode(Directive): - """ - Include a code example from a file with sections delimited with special comments. - """ - - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = False - option_spec = { - 'section': directives.unchanged_required, - 'comment': directives.unchanged_required, - 'marker': directives.unchanged_required, - 'include': directives.unchanged_required, - 'exclude': directives.unchanged_required, - 'hideexcludes': directives.flag, - 'linenos': directives.flag, - 'language': directives.unchanged_required, - 'encoding': directives.encoding, - 'prepend': directives.unchanged_required, - 'append': directives.unchanged_required, - } - - def run(self): - document = self.state.document - arg0 = self.arguments[0] - (filename, sep, section) = arg0.partition('#') - - if not document.settings.file_insertion_enabled: - return [document.reporter.warning('File insertion disabled', - line=self.lineno)] - env = document.settings.env - if filename.startswith('/') or filename.startswith(os.sep): - rel_fn = filename[1:] - else: - docdir = path.dirname(env.doc2path(env.docname, base=None)) - rel_fn = path.join(docdir, filename) - try: - fn = path.join(env.srcdir, rel_fn) - except UnicodeDecodeError: - # the source directory is a bytestring with non-ASCII characters; - # let's try to encode the rel_fn in the file system encoding - rel_fn = rel_fn.encode(sys.getfilesystemencoding()) - fn = path.join(env.srcdir, rel_fn) - - encoding = self.options.get('encoding', env.config.source_encoding) - codec_info = codecs.lookup(encoding) - try: - f = codecs.StreamReaderWriter(open(fn, 'U'), - codec_info[2], codec_info[3], 'strict') - lines = f.readlines() - f.close() - except (IOError, OSError): - return [document.reporter.warning( - 'Include file %r not found or reading it failed' % filename, - line=self.lineno)] - except UnicodeError: - return [document.reporter.warning( - 'Encoding %r used for reading included file %r seems to ' - 'be wrong, try giving an :encoding: option' % - (encoding, filename))] - - comment = self.options.get('comment', '//') - marker = self.options.get('marker', comment + '#') - lenm = len(marker) - if not section: - section = self.options.get('section') - include_sections = self.options.get('include', '') - exclude_sections = self.options.get('exclude', '') - include = set(include_sections.split(',')) if include_sections else set() - exclude = set(exclude_sections.split(',')) if exclude_sections else set() - hideexcludes = 'hideexcludes' in self.options - if section: - include |= set([section]) - within = set() - res = [] - excluding = False - for line in lines: - index = line.find(marker) - if index >= 0: - section_name = line[index+lenm:].strip() - if section_name in within: - within ^= set([section_name]) - if excluding and not (exclude & within): - excluding = False - else: - within |= set([section_name]) - if not excluding and (exclude & within): - excluding = True - if not hideexcludes: - res.append(' ' * index + comment + ' ' + section_name.replace('-', ' ') + ' ...\n') - elif not (exclude & within) and (not include or (include & within)): - res.append(line) - lines = res - - def countwhile(predicate, iterable): - count = 0 - for x in iterable: - if predicate(x): - count += 1 - else: - return count - - nonempty = filter(lambda l: l.strip(), lines) - if not nonempty: - return [document.reporter.error( - "Snippet ({}#{}) not found!".format(filename, section), - line=self.lineno - )] - - tabcounts = map(lambda l: countwhile(lambda c: c == ' ', l), nonempty) - tabshift = min(tabcounts) if tabcounts else 0 - - if tabshift > 0: - lines = map(lambda l: l[tabshift:] if len(l) > tabshift else l, lines) - - prepend = self.options.get('prepend') - append = self.options.get('append') - if prepend: - lines.insert(0, prepend + '\n') - if append: - lines.append(append + '\n') - - text = ''.join(lines) - retnode = nodes.literal_block(text, text, source=fn) - retnode.line = 1 - retnode.attributes['line_number'] = self.lineno - language = self.options.get('language') - if language: - retnode['language'] = language - if 'linenos' in self.options: - retnode['linenos'] = True - document.settings.env.note_dependency(rel_fn) - return [retnode] - -def setup(app): - app.require_sphinx('1.0') - app.add_directive('includecode', IncludeCode) diff --git a/akka-docs-dev/_sphinx/pygments/setup.py b/akka-docs-dev/_sphinx/pygments/setup.py deleted file mode 100644 index cdfa31d397..0000000000 --- a/akka-docs-dev/_sphinx/pygments/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Akka syntax styles for Pygments. -""" - -from setuptools import setup - -entry_points = """ -[pygments.styles] -simple = styles.simple:SimpleStyle -""" - -setup( - name = 'akkastyles', - version = '0.1', - description = __doc__, - author = "Akka", - packages = ['styles'], - entry_points = entry_points -) diff --git a/akka-docs-dev/_sphinx/pygments/styles/__init__.py b/akka-docs-dev/_sphinx/pygments/styles/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/akka-docs-dev/_sphinx/pygments/styles/simple.py b/akka-docs-dev/_sphinx/pygments/styles/simple.py deleted file mode 100644 index bdf3c7878e..0000000000 --- a/akka-docs-dev/_sphinx/pygments/styles/simple.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -""" - pygments.styles.akka - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Simple style for Scala highlighting. -""" - -from pygments.style import Style -from pygments.token import Keyword, Name, Comment, String, Error, \ - Number, Operator, Generic, Whitespace - - -class SimpleStyle(Style): - """ - Simple style for Scala highlighting. - """ - - background_color = "#f0f0f0" - default_style = "" - - styles = { - Whitespace: "#f0f0f0", - Comment: "#777766", - Comment.Preproc: "", - Comment.Special: "", - - Keyword: "#000080", - Keyword.Pseudo: "", - Keyword.Type: "", - - Operator: "#000000", - Operator.Word: "", - - Name.Builtin: "#000000", - Name.Function: "#000000", - Name.Class: "#000000", - Name.Namespace: "#000000", - Name.Exception: "#000000", - Name.Variable: "#000000", - Name.Constant: "bold #000000", - Name.Label: "#000000", - Name.Entity: "#000000", - Name.Attribute: "#000000", - Name.Tag: "#000000", - Name.Decorator: "#000000", - - String: "#008000", - String.Doc: "", - String.Interpol: "", - String.Escape: "", - String.Regex: "", - String.Symbol: "", - String.Other: "", - Number: "#008000", - - Error: "border:#FF0000" - } diff --git a/akka-docs-dev/_sphinx/static/akka-intellij-code-style.jar b/akka-docs-dev/_sphinx/static/akka-intellij-code-style.jar deleted file mode 100644 index 55866c22c522de2f21a4fb2a6c26ec30ad3c5486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8587 zcmWIWW@h1H00GJ33DzJQhPfG77?Sf-Qj1F}b5e`-|D9rB04Ww>;9%fjKvyisz<{hc zF*`dk9;7)QtXr=lH|OmQ$NVM(3AP8;`xm{ObXR8An*^gPA#as9n;MI5wwkQ7N@rE~ zI<`MP@QUkE5#jAKzqmc9{=KyJl8`}EyfL59whr~c8x33AwODjy-0~+E+-b0@TzMsN z^-9S{eB6&7TF*8VxFnhFU^VxWSJ`eM{or#6!ORCbo_QPk#XYRH_z)n^zU=N%vyTcM z8u6X%r;m0yE|6E3xpX)$PR@ck$!gnnxd@SUn`gg193l7NO!%JHA7_|btb1o+W|%9V zx|n_WBLCLFrdykq-h8t8lOO-i70w%WpYGA5Ic*P1k>{f-#}7OoQunA9p1vH%mHnbs?o-sqn83SiSJ{16Yze*SrM3G0#;&PX z)_RjwUxU}qQ=?b2| z$LCL3wyc&pz?+@pgM)Hg3nK$VgCKHznxaL%AOizKenClQeqOPDeo01Z5hx0u#{4gS zv`g^+-@l@IZ%f|Y-7`aAl6R5st->CTea2>6eT&R^u3Ko+i$=8wuCU!ng{`DX*|4Fj; zp&LDOCCnu>1(+kZ2*iDOwC&qV1(Ek2-i) zyk|Kl;@%o?Roc~W%LbVjfyc_lS6jCyG5<2}^JIBtP$+YlTUTPzgkID9Y_Hgq@(Eo! zDfZtcOxvH&abL#1@x6MVe_^x#I-i&e*AE?k_Ji|$!B&UL3<;0TIl=E1+HEpjxnJnn zo;?=o2JJrG2ik&j*!w4GYOE=nGfnYiS6P0!=vAk-Ol99)!GYR%cJ=sNW?TA2)OV9e?BnDm(a#o}Y!E%WZ}OA# z-`ni2?AVf77sj^jXXxgt6HSTVCSJX4t!BP-P4==>o>XshpLKo9LcX6!+I-G`!nvkZ z-gAvYeeVkxPYS6nbDtRU_ujUBd>5u2I~K5+`>$v03yGdp_5oL>Doc1?P&TYBb?V%g z^KjDT8|554?4mrCR=+hOi_V)(Ff}o;-kN83*2CGm{af21pL1J&S1qra%U~73l`Nwx ze%#cIxzqR9sWS)WyUt>H^jr0(^xJDz*_(B8^iQ5YXa2lg$ojwRlSvs`lWu+~pYX@p zH(#jYqv4ZxT@D&u9x4(RDuFsDRAy9MR!RD}%Sfa)h==pg$-SFiy%cNrj^;~Ht-8|N zrz;)Leob%Ec@Ew;rn{P*Dy;WsO16iL05dQS-ab`pX8Id ze_)ErMTzGcJ~LbE472j3CUERl54`8%q4a;-M3;l^=Z~H{Zu#}`c5{>)@5QLlcRUe?ET{jO!>7cf(4s$W?dgX5 z6V#Odb>u1(uZT)((<|k@=^VW4zLdo^!HJ7X73N8K#2r^vsVY_4-sfRHWs{?ylF{bl zo-Upt?y0AKC0yOS(%-Ew{(79;tZDc3Ppn$JB}M7B%dC|Vru6>I&`|~Rl6BA z3|a1M6PC#Em;|WK^nclJD;vOCY$m+S`|l}NmV_nzE9&^U913~*S99syoV1HQaoLRK zs>}ty7ivkG{W^3dxykoq<-x^CUvr8prq5io@0o4sv-y_icZE9k{p7j1>_Teiv#`fa z8^5Z4{(P$8ft!Ec^2n1n z$~DdgPJGW2e6c6;-wlC?-FtqoJ$?FgkVEa^Wk-)cJHKB|MQ%^Yv}VCqM`|AkZx@=&l&dt0#n=a1eRqqJ+Y&egB=F4#5gZS_I!GF7wm zEz=a2PrkY}FN&+(N5% z*@u#y8=vfAc%FUtZO>(CC7EB`-A`l+ZT9!W0m|M4^9b?M2M^7R6CfkGd6W?c3!Vn}#k*p?Ax zuR3Slrab3tnfzHk(%v(!>pa{uJB^J$dqdJZ#y`s+E}CdHbEaI*75&3=6xYfn7gl9S zCArS`$=-eB<)XqTELS|w_w)S8e&qV~wea$MuD9_l5smeNGY;?f*8FnPewyIlc>C+? z&diZ}T`jDmf6PuSk9G2y57t{NKIAnlo_YA2`YYDLUxjIGQiU65tmA!eBJ?2Y*c`jF zI;W+R17F^lF0k&%o!!~br(WLO&meeo#vR>P2etJr&P4t#5{Y^7Sn|x8tsJj+AA9M0 z&2Ynf5gi^IOSV_DFRrvWYIs?!cDm}smxTr2w#i*6_|>~pd*8<-2b1rweirOv%y=(x zK>xd3t18#mk3HhQrdp)6e>mRIq+6KA3k$*}fao7kr6j=9pe zwJ!BBa%xKMf3QR7d%e8M8;xUe1t0$GzL-$#!FbwyzPrHR#cI9Be67lA)PGkqIh^7S zn)JS{^ES&-{~t%XW$za^O-?t;+Lgj))Zd`7oijyL_vQS_C6`;5#T(8%`hEAdBn$Bt ztDo*BGoKzanSV5w3R(JJZ9h_R)Ap$Ge~!<8<7$>Y6nyq}uf_WJ{LgRk z{%u^(Kl5cQ`{eI0HD`#dIoEjEV4m@*b0;#R<}9<~o^<52aCgq5B>wQa=$z~X@rdAk z#+Tw`+O7Q;x2x$Km}Z(V)i?e}U+bl5W&Y;n^W4*QudmvDuQHzxO!;?d zRnLUiF1GK_|4V=Mx`llz#~#hucUDBNiDBo9WL~qLd2h_&!iM|H-50hoEZ!F!STAkt zcRzf~yKDancKuzPk|9vOz3^d4Rf@!}K&=SPKegA-)E+uBlX=FTq;(l#l@sdu3rhbO zHMmaS;e9%zFzV=maxvxfKS3g?W-L~Hdko%HTwEpcSXWSc)`_?2XAiS(>zdFJDVh3Z zb<=&X=hNj>Tz$Efd_M$6U%Q%E|J3ESP3T1*@1W2tH@m&2EqH6kGIj3egMTM%Tw;5B zdAIZy-E)0;>deWXYnFXq8oJJKmM+`rn-LS^W9#?W{5=u(ApWG3`HZ_2jI2+dCYSR+ z6Q3@xe@k5cyuMe>^&fAH+_#xaANe`+cUtP#S${OLUmo!<*%~!f`9;@*0+Z7xAL?d3 zUVOV{`_bPkg&&8fD^?|Lk&oW?Cq-iF8NQbSwV#}-I2OM5eH3ov74JVUIsIqaf5V>I zPjg%>jHi4p|7{o?^G0Oa6_dFKWG7aB+;wne&)!!FraGTio;2m#wDRt;^X2RZ9M*8% zkGtBTySg&sZg^PQvDTPhznGaa8s$X3%$Qmkdj0yFcNWa;7Z*Lc$I2|l)jdh6+vswK zN@H|r_hxUFmdh*!%Uv`*ikfx=8TttcbHpF{uA8(>wLT^*Vq)pR{49?0vLZ%-%4HL8 z%zjcHu}VGQvhLE^&S!$s*aB-;XP#Ez3W?1A$G=IF$GLp(pGV7frtJ2YN_-gk!upLy z#$AECZ{&J^vS|O8_{2PGKO@)6zF=RmLeJDPAuB`eS0Z~1n|XGwXqynAqi&*RJoCqd z$@xjMstYx=ug z(XWN`?GFE5HTUi7zvoxg7D4e)6>bab9-WlSw)%zRs(I%EHp>YESLd;=6h9baQ)rcJltDJnkD` zj~-R!x-GMUYj@?rGSM6NPDI7NU3p_)#&-KTvGa<*{TA&16dXHi=7UZDonEd^d}92- zq{CnhU&HK-e|r=+92fg(^!fdU!;_AcdQ82)Eawzo%FZn-Sq#6`zMniPYa8c;%?VfL zoc|;ExS&XF+s(H@Vb_#?%au&|c_jC-X5Zodv&;M$X4xK`+<*Q0^>AKCBm3La@}6@_ zKZ(7Ru;R(BGo_rh3%oD4^5?9r-j(~uQ>sB}vqs+c5`%?(Nq<((ysNR`?4<{cv3;}7 zFPL`pB>P6yZJ)k-zWI5R`Qy#bBLWPQEdH(y%(=haZ~eK`e#IM}l%6$t{-)VBea)&T z^X6{%ukX0==<)h9d8<^mM@@e#uQ>DW{|}Ll-d8iC*S_vv%%OW;-`Gq3xVqm9M|r(% z{+~jBKRR4^B){k9Ot%HTyH)4iy3nb0QT*-a)$%6i6OBIYEqq$BUjO{Q`o37BWxna} zE>5dGXQ#5pM#*(jsFD2^y>sXK?T;`0KJ{2l-OaS+OYBe7YqQ_lXSd&`??m|Vugfho z;NL6WTrG6?h-qT0B>+S!QLq|IYU-Kb+TEH@C1{_o$Isv+3`cp40EXt$7@(7}s+1 z<{5Q{KdO`O^?CpP*_(5qe%Yr6i}l8guln}{3O$xOvd1)VmB;V<&)iP89NxQQ&#Hx$ zvvuZP+j4J`-rKnbAD8(2e$MeA-f-UWOZ8qm9~%d}|M|bOsQd1gb>bIi95;7wxc4;4 z?a3cDb@s^fv+aI<(D%#!s*}EoT_^qVf+;cPd;gx{yW>=I;@%_i;H`dVR8p2pCOtiN z<@QteP!kWa%S_#;OtYu^d{gF%n|8*gdxCmb&f+aMN)|6-&p(p)GVtivG;!u5N7l)T zhg_8wzR7>2r1TmH_`SNrblc`LnHtxU1*=9U|a6VxyBG79Ajot;y0cxDzy?;&EtM<|Nda&1?e|y_1q4J9k%uGIiY)C z=go&E=Dgf2PQSV%zHmN%o3%4@-Ol@Q*|y%+24ejGes8F{I_bF)`9i>vr9uK_nho&%U0f(x$dvhUH|`VpkDk>Jy)}Keg=jUevn=~ zWC-VL>{Tn+@C}IOV_;xN%gjj)NzEs_4s z)8&zaO4ia-?ccCv^VL$gHMHi7B)C zmIOpC5)V3gTG`^jIjckU*WSMW@Oyqa$h$GMvf(8R3=9((kiDB1egnk|pg<_W;#G8Y z!VC-y2zABDi8+a&;f=S`;{6X9h#bBDQ^b6#K<~wavl-bU6aH}DE||?S-$#~pddb^2 zR!8#R-(ZsxF{&||xc%POJH`34K6_uwSSQL*=vT!*R^uZz|@JV7<;A)l)yII?q7cFYt@3!HPiQl;{ro9i(TzDOD?QGu8 zqQKQ=0%ts*aN19KdEtwkjT}phC(ESUDFZd9Tim`=i}p|d70*)J+S)(=W!ZycHVaE-xrAJI zKA)pg;PcevHZ$Y0{2#VOD*UE9zw@N$oxAggGcWA^j+J|k#h4jYy_yhOzz6^-8t_J7qi*TcV@eTkJRTkIvsG?ER+6y_ItybA9vpl zn!uY8tRZ>f_-}SE2fZtsCcJLg_oR8Z`mMJXc21F;eFqp$My=k(m67XkxzG8;%gG*b zP7d0!9!pXVyVkC0*;6>#pzlufBR9|cOH(-07It%e-=y0n6e781ik>A~$Vo#B2vm*{m`xIaOpw&BY{=RFS6VSlRBe#(J%98cH`$}S+5;G9^G$SxXLN# zWXJVOx>HzK|Kkj+|zNi_Ueet)r{PDm^@s|&M%9+EXYc2Kfrpc+} znMpSdPCZ_!`sJ#WWukHP{+?LV?l`k~H~sQwEPeUstXNL&%&&(sD-Ol!oXO9a)xYQs zf7E^J+j{q{<$Q}{?%gacm3ht%ihvXCJ9j!VGB8YGMvj1_fL@e=Vo8(;C{Il)PAw|S zOinEZXR7Gv;@jJV>dvn}uwoXU?PKPhFTL}!ju*aBoB69q$MWTwnZ|M*ExKAF2bdP9 znojoh*5iQoMf84LF;^ zes_XKBfF~Di_iV`f3|$z^m}3-TiPAY3pby=zoXvOt@p|;a&^DN+=XdH`OlYjYi`)M zD$~r;`_A5FuV$<=n= zH*NKcGNzoE5U6?4WbQmeuVcLBo3Gz|vb$Y9f7i6r;w;xb9>3ReXM!bL`2nSG8@E1t zcxQQGmXOtb$N3NS`&>_4aS;4}IY3~3lj6ncQvwgNb!T>*e>r9KHXbXD1((DVy>7k# z<0dJ3YwEY>8$=#to;asEcl~_5Aa>0S-2~mVf6|P>tE}?G2eV2GtuMH z75jtE`5hc5HBQ-VIk{DV=h;Sv$xDA_Jk{Xl2xb@5VV>HqGxJvI!$(q+XZ%R+;>_s& ztFgoARn+{#n{Ly>kL%WUrtt2xJQbq)Tjs+=rZ&IMfVi`B65pt; z-q@v9UY?L}DX%gtWp{dl)5bim(2k<$b>}j!Zp?l2ym;A*n3?Jo&)63CXubb#|0Z5; z&OS?>rRy&}5dCy8()!Tlhqn(Go4;Hg=ean1ug+Af&sm%1gbQXJQwZ^Fw_0s>S$yZl zws#FKfmZw1@vmK%_jTfRhdsd=4YiJmM!U98NdEC+iMa}s(}M}DhV42Vn6v2UEuRzlg;D_y~ma>=KOl~|G$2_<(%KSe@zQ|XT+R)Gg;_mix;!O$J&&4Eh}Ap zn%7S|_+PW-y7yb5RljGeOuN5cQSW=v^fMcSK6c0XFaMNrW@**OocA~5^x2=Ql}7Q! zMqd{Gc~(1$Ws`Skxzo*M^C~sJPWcv-F0j#=qvS^U(FBZb&&M3!a``u8o=A%=RX8LOzQ8R&tKxZu(c~QxH`lGXbzt?@gK{!F-mCZA zvpcZFZiA2X<|#{Z!Y0jMdt+Iy<2v^|h0QA$<$jrDG%aQ7@m04?qh9}RTAK3i&q~gP z&0APnFX{Z9|8UaFudlLBEm@&fJm-}5PCXq(iRi4jZ3niB#>ckqc&)=aUF%@b#;udH z{bgCFOJ3!vjos_ zYZ@F0e$pV|I$_z987?>LE{DZDtBosOx_4f;sFm4cWvzz%hNjd$?_bkTEO*@;KX1$3 zGvZTPA0&DFir)5M17|q*`Z$lQ^`{qK{`~mw!w(PktMt#JXwM z+B)CK7ri$3^?0EY7Z^SIB+?-89-f1GQEd)^#(ewHuq{Z4=I)BdrqE^$87 zo?~B^OP;YWYdF96b6H2c;$HCy`afe5%JO@qd!t_IUb&xq)?VInVV$U@55Jw#zDG%c zjdvd%IW{TTGq0<7A&>W~S4XlAD4!SoP=5P}|KjTbA5N{0x{$kib?%9+tJj(F?v%L3 z(sUwV@zju5@wnYbJ5)}UE&DE3EZKZ1(p2Z6N4s>}j@|D$)}`bus68QZPwhgkiM3wp zq*?P%c^|KQnd)+7>dXC8vuC`#eX4HZLk|8(v$yLM))f~oe0lHSWp<0dyD!VGUj90M z)2jX9S8LewTz#wWgeN_>;k)B==bKpgZHGC3r28)2pZxRq!EYM1)l>G_di{?}@VpZz zf9HO=w06$*zeSIyT}pn-ukh~uY1W2wpEoz>|GCZjob^hyLh0|dhrUI#N_=HVefVj` z@vfbl--{K!@7P$S^l`?l+w-EQ++FnMvD3{xS$XkQdD|b)PW;evrd7J-pihLF&R&&O z_Rbgl99ZkP&pO_6S>}G9ed`ioEtS{=q4o%EhXXx_Y|VbJy(4qtc0ci&j z)i*D_x+3MT=;Sxs|JPaTobHEOvl2 zIY4cC1_t!$Nm&L42G6{b)SR45F9lB*S4Rc+ocyH39EIT2l9J54^x^<-MkX!>h-UP; zYS6?ssCR_GpqXm$M0GKAnwybHgaOjp1ZhT|G6hX^BQ)v~oc0De1ZEb<7eDn79XHS< zE5fY5j98{zLE2&dz}CA%Xg@5-fYH}OcmveiL+(T=A~Z5EFucdmi>2>}>=g7iI3%E9 zW^NKf?q7lQ!9oC}54lwj>WRU0F)-Xh(FgCBp&NkQDg`zE5eBRfLADsy6+qSxYP%vQ zF;LqTpr5%(GQ`zk9!uLS~AsQn;zFfp39xYDT68?trEmh5xxNm&iO^D3Z{Cdy2%Dc zh6?7EdWNQ^=H^B^3PuKoCi(`3`i923hL%<)CRPRp3Q(YAr(jc*l4cd;;s&*=C?(BS zDWjyMz)D}gyu4hm+*mKaC|%#s($Z4jz)0W7NVg~@O}Dr*uOzWTH?LS3W`avnUy@&( zkzb(T>*>cZh>BAW{Q=$xr>vDp_!Yh zk&Bz5p{t37fr*Kwo2#3Nqm!wTv#B{uuSMv>2~2MaT(7wSPQ9Q60SXi=m(-%n zveXo}qWoM1u*a=3al6F@r+HAlDLCC?=899VzMX=NJ}7#Tq8la@S0amD(vF zl7DJmimg(SlD(bhF~$-G2DJ=N7srr_TW{ua#)Lfmb^QM3Gi?VBG(4EZ)U_bhD}t*l zLo8~_)4gv~U#+dbox9O!cV&L+|Ge+l-o{_qnzt>#Ec)uEyq(f|JK}_=2L(h<2@z-u zoiTIs-}&WfF-{5Rc#6~5YU<{npLq1}%mq0A>t&|>aYh);IN=<=#KG{;W9LELSOdTh75dVane6(^TSTobBKLP3>-j z;^Mm#cg<@Xd_XRk7R9H5bV<`a^s7Gg zpzfr~n_H6m%~PJ9OR93|VKZOQ{alHV`En}5&xpQ)Z{_-#kr#<>b!#fzWYGgVlPd_^nrN+Z{puAq&EAU>j{VcR6v3Ri=0K3EM_XLlH}AA6 zpShOTXH5OQ-#EI-6ltQ3VmgepBE?h?s4-Bx42ZPuMrFCdL9^Z{|P#*&ZMwEJt9x5_s<_) zE2(q*QeKNa-^{+^mu21Cyz`gS$IrVL2uzAP{?ICEj)CfBo8MPO8BT1R`>H-f($|Ph z`I$9W>x4H_4JPN$?Pg`zIj7)_f-hs|MHP@}Q^TLlhT7kScOH~_`1Olik6NHcOG^1v zJKNpus`(e&1up*e&0EEv@h{P&(@9aqS$cxcm8xjIET2ee1F4yK=loN=*H$#}Ua06%dwZnf<&>FsDw!8;m;llpu*CnoS=1-7 zy_qLYR0ig);$J(}v&6T&!X@d(lb6ODmVneeV6;@SK4+7DFUd~v>AZw*_GJ>j+f0NX z?>H&pyC{I;qwy~4|u%ue4w>->g0Qx|f1^r!`{U`S%z{J=!v?B>tQBsQz>S2w>J z>6FyqmTGeI&s}$UFHzOf*i~g_(GtfJUU`bRy2oTsdb!TiC{bc{NbMOvZN?Du{tIWs zn9KyY%@P#S*LkPUu-ef0EMOyJ%acq8yQDLx{CT>0w zdqkc0Tv&?c-i6V6iS)wBFKQX-j`Y-GAr z;q!L$LAFZ=*^CabZ92dvbXRogLmugXI}?_eZHUcV6Rkb%{e2Gm=xAr*oCZc|kGB2% z%Cfny4jQbv&E}_|Qai!UHd@^7@y6*tTBfxB*?08jPC4IAG8a{OyjYg+knQ>DR?xBV z$lK~J6(QGxEnmZHBfamm@*Ivi_w|*#NcCwugAe))GxE8g{_dYsB2p2Tb7P70^rp$* zUNTJLIs7{3?CJe7%AtREsn3XX^gn9SxA#-F$N7pA&1KFi>Y5RL{vwr&a}Qt2W^`cG z)j#~gGoNwKG9k}55|buu{vg+$%X+%Vx<$oia`)S-?fw!a!t-ZX^R>4^3TU&KHu zde;0I-x(L1$BAD0+aGH%>&Y(_7s5F_+%dCT&(uD?U3i`Gn)Q-a)o$# z+$G~}O``8D=DGw%6z~bh%=_k-@^Y`^T5Y985)4mvJM2GwxAH(agFMswki6R)-tb?# z_-U2{(|BZK=ZQyuX@U&x^0kS$#J9af_z-tn~f6q_WyS&!+{@te>CX3!2o^Spkw?pRMvq!&P zJt)6&`$|car^<|K2dBChmyP}(Ecm0F_3OrhL+du@pWe^Nu+#oP!yoy5^`|Ch{d%O> z%eQgOi?ZYX(w}bUI;!ycnfvZZ7fBbA17) z>dIH<+;w$lSbm)O#$>nMtDQfOJ4A@_-VuwcM^h&ptGDd8`ZmW+Nlt5C>g^qmvZW-q zeLlC{@yd3#90g}?>4uI!<;T`&?|ZPQT1tU;R{y&>(GyA-KiMURy-V78@Ro5%*o7aK zvwHZH1mYOdXS18`Ys@&J|LR0e$@yxY#cF3**fY7VekwTpynKSZekJ4l-;8$Nw_Ezd z?kfFdi#w#gtd1-5OT`oB5Fe9X{Tp0id+w!$yxG*~{$Q>>o3uf8D)YJX&q{ah`h0nQ z)A!zdgN~PW1%1bvnN9>x zZMwt!ub1a&5yOuqObY*be?By<6`2qedv-U&iF78O6CRImXxp>zP_6Fy!O-9`G5qE= z{k`6KYhG()o#WoX8(@8XkNm#d&O!D{)g6`R_Js1Bj=g=AJtM?zva{l>J(dlEmopd+ zY1>({TZp%|{NA*4eenLp%6nsd8RkngoL|l`?O)ad=8HFj+#eqM&CKIryX2$rp$&^| z>eg{jXk|DNy>#)@Z)LOIG#_BQ$0Yq=*J9q1``jZf?qnQ-38GB(LkTWn6Ke zym{9C-!F<+E?VMx`h1e|qN;}CGwja|R`Abzd7Y5m?K>X|S#&0zyZG&*zO$syw->@90h>xr zY)ia(cEYj8xpsO+vzpa@XD2Y*?rl>(EjMXZ|60{W8=^FBRy$Z;tk^VDoXzY4cTR%N zjRQ{;m@^M-KazrmcSs zw*K^1X5R6AK|#WK?xdgpTpuWG%{}O1Ro7A%=@I_&MbPDS&xF~|w(Xady!7-%)A{HL z`jbNrEkD9Lf0x6uixz2*gkwU^Fl)KrmTp;e=(a+y>)X4Fy=Cj97aRKovF!fk6_jtI zHtk)t=Z*cpz!;e>c^JI!4t@>ei>>|FQEHu~Tup5NR4lrLQspKa?JU9|UV+WlQ=iKn~P zAL|lj|Ic(zbk>xTgU=-!&ht$Du(Hu+hv0)?p%p5-e)BH>^f!3k_av)JJjeZ|&9?l$ zHSwar$E9}bI{2=dF8`9Nji)r~b(O5bAi9~93n`SIY}fnRRdQW>_C|1lE(R3cJo>oQS%MJC(s+y|u% zcX^#&?mK+%+rcJYfenq@6=L@<7u0jQB(5wmac%163L>)PK(2{8B8X@Gn~*Lx9eQB&Bb` z6aMit+f2H9+xDt@+|!Ke-^GgczwJ);_|0mdaUCxx zk(OKz4c@OTb6cEIaz=*GtXtC?iw))-TrhoM=1-UEVE39*p@K*Iog@E?EP1KeBW+ir z^zAvr35lr}zs!Dc=RB*#gv4_%J$S5Lo@P|=9hsd32_pAC(2S~(7k(iNNbUi|2H zwHTzS<7=D^3hrMerYTkN$r-g%XPsXH+k}pidLPa!hT<3DNuK)5o z+w>Y|(#w6%=LUB&=>~2nEUY~|=QB^J-;uT#Z>&3(rL*x&SfpT>`0&Wy&lf7{&$QaC zt~ji$Ua^le=fJ%`+&2z5@#Zw#*#7kY+^{1YC(V}lpYQ897yTpO+3no?^Dh}^DY#6| zDOoeK`|Z>REB$+!cpSd1yc4jxQ?NVrsP;k5)6BD`e>j)pQ!~Txb=OaZ`G#5#H?ux4 zHccp2d|70>H}Dew=?br_=bY7_JFSba+I%aczqc#Z!u!t8tQ?0;VY*Dx7oOZr&AzJE zu;H0*mma(4-;Otp?-*yzE^JWaxVU7|g?(!+M9a5zEOlj_wKr_<*0@!6+YA?6RAHTP z@Jsrk*UMHm^}o3Byv_fBTk>3m{*{bQM5^Zp4hvS zd2`N%*RJtew>Iz64M#60)6+a>P7k{?TX6396 zYnJU^-L3jN!*xyO{*)8Wlip81!=NzVFzsobj(LP~LBp}<8Iu|_J{5MTS>HAb6m+}D z_gjon$<{TQo%1eVX88RFUw>^mvwUvtWW`x-i;R0r(w^^g?4R-B65Ew2x^K5!DcjPO z`jREo_jk3k)TDQev-)`@EsLKn`?YSnYLAp*0E^7?o@smcWyJG%cL%s$+p*|mpnz}O z<+(THFLgGH@!JX=w5WPCWkJu8)w!t!f6o4TICHa;S+DG}__Qt0B2GN(s&gr;|1A9Z z1)tsHU1u41-`Xz@NWO8|bm!jI3*Q&F>ua7>fACxQ+~G-c-s^ZS-`=%oVy7R!WU@-n zMHh)+iyGeI*hE`~8M`i@FOi*cHO$2Gx0-zZzjurCmv#xoPp_%qdHV7Jqxfy@Ieks1 zO0Ujp?2$Lv;eR6dPU2$i;Cn*aUR_5vE!wNd{rSk1=Lgx!Z*70NS~4S0+VhgyPS4XG z{hbDv?TYqJ`zc&CVM%*QYW!5m!ta;m85P(|fBtjla=mqD(VAiom%J5@kTgy;}s2hVF`VK*(sikD z!m(zpoQAl0(=5L=dGxP)e|=4Ki@%reH5t!^Y#yKA?1}EVIr;vi*{_s#=_vR&O_aLd z>1H**`^41tmkDjfLOPb8PxwiNZt7Wm(s$3B-HX&Y4}G4xtV$_dR`JolyDbtvExlce zHS=8#ee+#Zd@JVruIF2RD$d$+D3m+gpFi_8w}7<6s{Sk{&s!!bC2c(m-Wz+Kz7=e5 zxz?oOuIjHX7uRnM3A-bCBGlaPVp@sy+HT{^9A>w#TYNk9J@@r=Kc;|NRvCg<54tM8 z%+!joaLDNhDP9vHEM1_RBe8xfZ;RjjCEOG0&C;IMT~cMw$k;ri_^arp6#-he-QT?4 zuf8pmyR-J~c9$F5n@^Y?f05M@_P6WK%V*oypDlmI@+H!wibdko@qU5heZ1$+mx<_< z{(JLkf6MtvN6&rrHS(GIIq2~$&y|+5e%9`9?2O5If5stCU_dQV@?Kf^X-|AmVQlVhUqa){Qo9{V8|g@|u}|(1a_?)7v9IiPdJDIPr7#osj!m)pi7X1X?sYdK~8yJU%V- z$hJ?~N%uEQX<&9-a{a^YMzOWezgi}q-F-==%SA_9X`5;H+?R_4)f;bpPceCU+QZzU zgIDH>xPROGH`BKqxy$EUzxaNHE$S}PR#Q!t3SQ!=>JK4)9uQoty+8Q=SN6L{j_gl5-rRd;`FYw0PR+}^uQ2eg&17`xy6bjikyBFi z-WfMO?^jIv`0jp_;f%}nD+I00tyIq~+mZWKNom@jN4I3H4!sFBc{%UM-1mat)@d3v ze?4sc{!6*a!yYBwkM%rZBAoA4yW6|oZ^(_>>6K~e_~7;OpxCpkv&xn(bdSBT&wgFG zQ+%)TiOIY9_IjT_v~lqQ2CXxZt1i80`kDP@$IY_$nOPCb*M&`ew7{wQ#Cx*~)(6k1 z^VZo2mF|(aX)x{a2K1TmHf^u;Ev^b6p-N^>Ur_`uRIw z3$%9TKJNPY;rCCiL^(J1*$i&E&o)OyZDGuLu;Tdh9g9vzCNN9>`{G!8>xKA3+aTtP z>asE(yMD>%GdSp}%gnx|%9b&wfaQY8Rl&sHQ4No$Go18Yr?$p8Yss2Kr~k4Kgudk{ zf9pNXAuML6m2*mdPoLV;S*Ma*3v$9Pmol6a<3H!7yxilzg?pNu#qrQMtM+)ClRGD^ zST-rI@|)M|gW|iY`*QzYvVQPARqOY^q6e}6UVZ19>i4Al#x=$*>2pmTo;3Z`VF+*Z zn!(RF<9~OUPx@Y`y<4L;g{=(}R&;7jW03wKkh5UFea-=kv`6!IteCNT@1r)I-#N^U z?Mt{3qfZm$7bM2i_IVX6A27TxY00%er#)@k-K+197cKGbwAygbVacSuNA{I*8up#7 zo%7!O!s?7k@7^%`Zr?5$cl3+N^v%7D>Az>aeq1dq{O_8C*~??se|}~=_hnO1>cL|X z`x#H%+q7`+#Y~2$iYKPqUr?3`alQFBSkAm}Ud3kn*^Az(EQu7{TxJ_sPF;MS8NKG_Atr_Y;-B8K<}+)n9eT5w zmqldKuP-@^Rr4>-ZtIyN{&ZQD-IGM8hZQ)x|wXGCA~D67Z34L!>A{naG4{)YXr$J~zIdGEa1`MCPhZyy)O zmP8m^)ZLoEzu?d0Q);@0)tBvK^u3r^x9u)pZTGt$kK1-0-|6vAZ}Rf5FC){}{+_-z zlr@3bzABM9Gf#R3-+|B9*w|*O-P^#Sb#i&F^=ob!WPFQc6_&WPCFO%<94B4>FFKI7T%Fq(Q*Io z_wTDh!ar~H3UJ%~`yZ245Whh@*VFG)PMH*a5is;f&U!7@S{wauasu-raWesSvk!_4 z`K)`szdyjX$a(`KUyg!o&I8d6jJNh09}SmIC~3<+_e*AKv)wKC;&q}XF9pl(|8gEK za(0rM@XoTmM8NIF-kBcmr~D2si9WUUp_a>(-FlCItKVnw`#f`c-#1={7sh&8-^4AFuB9-_rv&)J}-ZUhtpoO*6vRG`Gzy}0#a`NG@sij zCVuy`S#sJryM-0kg?@w@mxk=zR%P$vce(awb=cGbaBPN#~QlqjNRvFLzGD zGIKMApOY4Q%gtgoD-g(8a3Yu4H&1$j=r@P$ygba(53F*T4L^oA@!Ig4ec=4FDsIx# z2s5>R;XnRW6ezxYRX-=`%)CGI?u4XszGRe&T6`;dPP5^mf3Xe>yI+^zjSbj+Dbyig z@&DG|o_}nMn#J^c{0l|$s(2C%y4*Tfu?HW>xLdw#!?YbDZHenLPj9e(EU|W0PgTaH zf6Q7<>Y6HwRbAO}|DL7>U0rXVHFa&tPeqr=%e|4|&$Pcyv*@p_-_w_8wDIn~%%|Rs zvu?RG@?7|>Jmvn+fI4Su9s6*p<1a3|{olNF)1!CB?q?6O&0}duYt-!x*gLD^(50iz zjS0-m2ib~Dw=s(4JmB2WI8$VjuUWN!?XL^FAN=NTx_+mO@snV3*t_XP%~ypsF`JlF zEeTdr$l9{@=PZuuZC2`u^MxC1j8|Nd*1xcnZ~swt37Nw0`CEUu3157vvsQn<|J#CE zzSvh%{Nl{#uiGRwYh>#`Is3OHZt1Cg`=7u3d81LMTw}jf!%rTM@iUJMGCEfk^ zyg$<@Q{g6j;9FT}v*W?-jKVQ{J2VQiX5XIW5Hx?@+RaaNe=S#3R`<_a#UFbsK!A%$ z@ZW6zH$U$S?Oe9%_gCvx>oR4pc)oAWxb*rOtI6)`j67*9e{6F4?AH`^rWAa-a@F3m z|3Ix@>V5gUDUWKagpwT`D}OvFQ$KTcy;PNC!n~_o+qO9E;LTZ}c)+YcCg;J7^{yf! z9!v_=v!0*%J(qZ|{hTwY&(X03IzN{69JwD&g+utX|(tM-6N$g99KEnjp_geewt2bty zcoJuNWp`-mPN`E*tTr@0X57TM>rI)}jRVEpVSALa<1d8SVSC+;_!d4cU&+*&EGWz3f8a{dq7-fC4JG^*13?cdWD z8^+)vn3JG(<3P}cM*Rb9Cfx~t**qDZRF?3XF??DyL3Y8y&vO1I0>5|tw0?kHt?Pmsq)KvI_VY>Txfb-4!w=uQlUQ zs#IvprUjN!FW>$CY;p2^kFVM?RwJ)(iB~U7{k7#xdOdUKkG%oA^387?VA;@EnZVo> z&n&RZb>6`c&W1grISKP_v+*_Y+N_<*`-63oK-p`C2_=*7Y?;9F+7o~$jsf?aw>=KU>2Og9b`X-K!0u>Cmq*ZJ$Dpzys6N>_at zo`kQxw)DU7fuG?U;*WAm2e3Ar3k@zgBE@A>^DCL(d6^%_NwsaerwM=0QSFPJ9eXjk zeD3!b@&Rs!4<~vq`IV8GK0BXbvwX{;lS-}% z9C()4@MZ4=w`GgZ2d8viRps9+JZsPDC8xR;ugzsxbc%P<)>m8^3sYVNwFgTtxZv|~ z(;}TVuY#G2GoCYTX#Bs;^6ZJLcRz1An77=_fITOnqNVU~+ba0=!rb%P3qpf967F#FZ3|zwebv0UBeQhf3QlzYTyjwS zVETo%e;0SWj**M{aP`9-<_~x7Cb_;ebKNkXNmW|(u(Rv=atqTA#w_a`CYLR9Z$-_~ zJITx;8S3kt6gf90`YzLaZAU3fkHvnjQm!70U$lR^bU58mOTq1OM*AO;5F6u9JkmQZ zr{`~e zTK`?-8QUuB>_0bjK0V&`^_JQ8(q{cfidXh|7T$0^ae8L(ykwRiN~Xq-rQYy zwlTUytE=nq`lh-gE9+C7uRARK!{F&EQpGMmVNS8uq}tb7O0s`$Rvu{zZ^)6a`@%Eb z&1rjn(hRYq_bw@g{k`?@g^0MY{4oh1HHK7+KR23pxP^U<6<8wrLP}$byu!&3yKXI5 zHt*2cJmqg^wdV*Q?L7B@mnZtgp^Aq4ferGlPMU{{Qj3!BDsEgeqwP5FT7}H%uh+_c zzGb@gFoVF7h9wJnlB!%>Ub6ALTz^7nuCy78!z`BXU)rmytQLAUN}k!g_;%kJ{>9k~ z0_qx;RBYLE>1dMz)20N?iG5S%@p@P}|4(r_X>gpesGXs$nz3bf%cQ-nr#g=*=XqSK zXqq3jbAEDp{Fip;5^w*iZ(k)9QZ-a&Zup?m@LaX!dTP}_64G^f3>Zdljo z^pkOt?rO2=6ACZCxKNhh?or2l!bn`f-+7{*_oCgh@6{G<;B468o0+GzbOK8U>)yGq z{hTfLGR*t=j&s{ZhO^v^vv%f`yisY$m{lBnDS=^fn2ay4DkzlfXWgz!=Ct^!_~FTt z2Iiv2MM|N6y(EJ9U)@M$IO^2!sGs3zFT+vh55=)3e0*O`m?c!pe=FDVdrA!Z#AlP| zsOru2m#R@__#DNMwnn4AzW1ArF3W~~$cl2%rsvnErF-g+uQC_^C!DqXz z6Ji3DzU5|%eEjfluE57NOd5Ku8t<5%uX`sH@I@xGs~}g@>w7M1g57d&-`Pjhd44G` zzMP)T=UtVuDq;C@g+=KL0{%5DiAh&Ibp8E)cfC_PCR^mpGTZr*PrqyJ&P6}%x$kXT z`}<$@(v5lItX}1MG8Ox+eqS?<=WuO}-;wx}B!59SV8!KES9A() zT?sAAy`lB){$`KUfB#4%OT3*Q9sK`OaaMHUKoA;z14G-sF zuiMAOu=C*iYST;0wr$OtS@Occa2G4rQ*{q3^+M;6%YV-PE|v(6SQ^$Ka=QEeiu!*G zPxified^rPLsrbwgc+uNXVU5ak^4P;+T@nnR(-8W9dV6LKY1tR-85gXv+-$txx94V zxBGp&84}DcUE(>v@BXhBrQfaVqOSKGE#;cVbl{V2^ubLNi(=0-ta<;&Pd5657_nncy$vv&N`PujSy+PTamfy>|^!JCQr~PI3 zJxMg?yS^~0$dKWa6hn$)niAL5zV#((>7ROfcs8Y;p7t$YVy3Z|edR44yUG_VkD_+p z2{XC8#w6l9hibKWx4mAZ!?txcO-CTE82H5GBotB_Vx qk-Rhuq8Dkc7FfWm`tN=QW`=tgo}OE>$gL5y8q?F&&t;ucLK6Vx?BeYJ diff --git a/akka-docs-dev/_sphinx/static/favicon.ico b/akka-docs-dev/_sphinx/static/favicon.ico deleted file mode 100644 index 06e53b6403c29c0bda4c76329abf272b7df781e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26683 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 LS3j3^P6v diff --git a/akka-docs-dev/_sphinx/static/logo.png b/akka-docs-dev/_sphinx/static/logo.png deleted file mode 100644 index 8cdc42272e7c2652544ac46cb977cb2f7591dc4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10746 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 diff --git a/akka-docs-dev/_sphinx/themes/akka/layout.html b/akka-docs-dev/_sphinx/themes/akka/layout.html deleted file mode 100644 index 010150742e..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/layout.html +++ /dev/null @@ -1,371 +0,0 @@ -{# - akka/layout.html - ~~~~~~~~~~~~~~~~~ -#} - -{% extends "basic/layout.html" %} -{% set script_files = script_files + ['_static/toc.js'] %} -{% set script_files = script_files + ['_static/prettify.js'] %} -{% set script_files = script_files + ['_static/highlightCode.js'] %} -{% set script_files = script_files + ['_static/effects.core.js'] %} -{% set script_files = script_files + ['_static/effects.highlight.js'] %} -{% set script_files = script_files + ['_static/scrollTo.js'] %} -{% set script_files = script_files + ['_static/contentsFix.js'] %} -{% set script_files = script_files + ['_static/warnOldDocs.js'] %} -{% set script_files = script_files + ['_static/ga.js'] %} -{% set css_files = css_files + ['_static/prettify.css'] %} -{% set css_files = css_files + ['_static/base.css'] %} -{% set css_files = css_files + ['_static/docs.css'] %} -{% set css_files = css_files + ['http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700'] %} - -{# do not display relbars #} -{% block relbar1 %}{% endblock %} -{% block relbar2 %}{% endblock %} - -{% block extrahead %} - {%- if include_analytics %} - - - - - {%- endif %} -{% endblock %} - -{% block content %} - {%- block akkaheader %} - - {%- endblock %} -
-
-
{{ title }}
- - -
-
-
-
-
- -
-
-
- {%- if include_analytics %} -
-
Loading
-
- {%- endif -%} -
- {% block body %}{% endblock %} -
-
- {%- if suppressToc is sameas True -%} - {%- else -%} -

Contents

-
-
-
-
-
- {%- endif -%} -
-
-
-
-
- {%- block akkafooter %} - -{%- if include_analytics %} - - - -{%- endif %} - - {% block footer %}{% endblock %} - {%- endblock %} -{% endblock %} - - diff --git a/akka-docs-dev/_sphinx/themes/akka/static/akka_full_color.svg b/akka-docs-dev/_sphinx/themes/akka/static/akka_full_color.svg deleted file mode 100644 index 239d3edb5d..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/akka_full_color.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_full_color.svg b/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_full_color.svg deleted file mode 100644 index 8d02b531b7..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_full_color.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_reverse.svg b/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_reverse.svg deleted file mode 100644 index e32101e54f..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/akka_icon_reverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/akka_reverse.svg b/akka-docs-dev/_sphinx/themes/akka/static/akka_reverse.svg deleted file mode 100644 index a002ae7937..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/akka_reverse.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/base.css b/akka-docs-dev/_sphinx/themes/akka/static/base.css deleted file mode 100644 index 0ccd0c35c4..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/base.css +++ /dev/null @@ -1,94 +0,0 @@ -body { color: rgba(0, 0, 0, 0.6); } -.navbar { background: #ffffff; position: relative; z-index: 150; margin-bottom: 0px; border-top: solid 5px #15A9CE; height: 75px;} -.navbar .nav { float: right; } -.navbar-logo { float: left; } -.navbar-logo .svg-logo { - height: 75px; -} -.logo { margin-top: 30px; margin-bottom: 30px;} -.main { background: #15A9CE; height: 520px;} -.rel { position: relative; } -.box { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 36px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 38px; margin: 80px 0 20px;} -.small-box { font-size: 18px; line-height: 22px; font-weight: 300; color: #0B5567;} -.bold { font-weight: 600; } -.hexagons { position: absolute; top: 80px; left: 490px; height: 385px; width: 252px; background: url('{{ site.baseurl }}/resources/images/hexagons.png') no-repeat center top; } -.light-strip { background: #f2f2eb; min-height: 200px;} -.under-main { background: #ffffff; } -.darker-strip { background: #EFF2F5; min-height: 200px;} -.under-light-strip { background: #f2f2eb } -.simple-concurrency { position: absolute; top: 155px; left: 290px; width: 200px; text-align: right; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 20px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 22px;} -.simple-concurrency p { font-size: 14px; line-height: 18px; font-weight: 300; color: #0B5567; } -.fault-tolerance { position: absolute; top: 290px; left: 290px; width: 200px; text-align: right; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 20px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 22px;} -.fault-tolerance p { font-size: 14px; line-height: 18px; font-weight: 300; color: #0B5567; } -.high-performance { position: absolute; top: 110px; left: 780px; width: 200px; text-align: left; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 20px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 22px;} -.high-performance p { font-size: 14px; line-height: 18px; font-weight: 300; color: #0B5567; } -.no-global-state { position: absolute; top: 245px; left: 780px; width: 200px; text-align: left; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 20px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 22px;} -.no-global-state p { font-size: 14px; line-height: 18px; font-weight: 300; color: #0B5567; } -.extensible { position: absolute; top: 385px; left: 780px; width: 200px; text-align: left; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 20px; font-weight: 400; color: rgba(255, 255, 255, 1); line-height: 22px;} -.extensible p { font-size: 14px; line-height: 18px; font-weight: 300; color: #0B5567; } -.pad { padding-top: 40px; } -.normal { margin-left: 0px; padding-bottom: 30px;} -.normal h3 { color: #326a78; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 22px; font-weight: 400; padding-bottom: 12px;} /*#595050, green: rgba( 44, 166, 33, 0.3)*/ -.no-margin { position: relative; margin-left: 0px; width: 460px; margin-right: 10px;} -.left p { margin-right: 30px; margin-top: 30px; } -.right p { margin-left: 30px; margin-top: 30px; } -hr { border: 0; height: 1px; background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(89,80,80,.3), rgba(0,0,0,0)); background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(89,80,80,.3), rgba(0,0,0,0)); background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(89,80,80,.3), rgba(0,0,0,0)); background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(89,80,80,.3), rgba(0,0,0,0)); } -.slide { margin-top: 26px; overflow: hidden; z-index: 1; width: 460px; position: relative; background: #fefbf3; border: 1px solid rgba(0,0,0,.2); -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.1); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.1); box-shadow: 0 1px 2px rgba(0,0,0,.1); -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; } -.slide .java { z-index: 10; position: absolute; left: 0px; width: 460px; } -.slide .scala { position: absolute; z-index: 11; width: 460px; background: #fefbf3; } -pre { border: 0px solid #333; background-color: transparent;} -.tab-scala { position: absolute; top: 0px; left: 0px; width: 60px; height: 30px; padding: 6px; background: #fefbf3; border: 1px solid rgba(0,0,0,.2); -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.1); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.1); box-shadow: 0 1px 2px rgba(0,0,0,.1); -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; } -.tab-scala-fix { position: absolute; left: 1px; top: 26px; z-index: 12; width: 72px; height: 2px; background: url('{{ site.baseurl }}/resources/images/tabfix.gif'); } -.java-toggle { position: absolute; top: 0px; left: 76px; padding: 6px; font-weight: bold; color: rgba(89, 80, 80, 0.6); } -.tab-java { position: absolute; z-index: 1; top: 50px; left: 461px; width: 60px; height: 30px; padding: 6px; background: #fefbf3; border: 1px solid rgba(0,0,0,.2); -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.1); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.1); box-shadow: 0 1px 2px rgba(0,0,0,.1); -webkit-border-radius:4px; -moz-border-radius:4px; border-radius:4px; font-weight: bold; } -.tab-java-fix { position: absolute; left: 462px; top: 26px; z-index: 12; width: 72px; height: 2px; background: url('{{ site.baseurl }}/resources/images/tabfix.gif'); } -.used-by h2 { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 32px; font-weight: 400; color: #595959; line-height: 34px; margin-bottom: 12px; } /*gray: 595959, green: 49bf00*/ -.used-by-header { text-align: center; margin-bottom: 20px; } -.used-by-header .text {display: inline-block; padding: 0 20px; background: #C1D2DC; font-weight: bold; color: rgba(88, 111, 117, 0.8);} -.used-by-logos { text-align: center; /*white-space: nowrap;*/ } -.between-dark-strips { background: #C1D2DC; height: 2px; margin-bottom: 40px; } -.three-bars { padding-bottom: 30px; } -.three-bars h2 { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 28px; font-weight: 400; color: #595959; line-height: 30px; margin-bottom: 8px; } -.three-bars h2 a { color: #595959; } -.three-bars h2 a:hover { color: #15A9CE; text-decoration: none; } -.tweets { position: relative; } -.tweet { position: relative; } -.tweets img { margin-left: -14px; } -.tweet .text { background: rgba(0, 26, 30, 0.7); color: rgba(255, 255, 255, 1); text-shadow: rgba(0, 0, 0, 1) 0px 1px 0px; padding: 10px; margin-bottom: 5px; line-height: 1.2em; word-wrap: break-word !important; display: block; -webkit-box-shadow: rgba(255,255,255,.5) -1px -1px 0px; -moz-box-shadow: rgba(255,255,255,.5) -1px -1px 0px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } -.tweet .text a { color: #a4cc47; } -.tweet .text a:hover { color: #8ad3e5; text-decoration: none;} -.username { position: relative; top: -20px; left: 30px; color: #888;} -.username a { color: #235561; font-weight: bold; text-decoration: none; } -.username a:hover { color: #4ba11d; } -.time { display: block; position: relative; line-height: 0px; top: -16px; left: 64px; font-size: 80%; } -.time a { color: #888; white-space: nowrap; text-decoration: none; } -.triangle { position: relative; bottom: 9px; left: 40px; height: 0px; width: 1px; margin-left: auto; margin-right: auto; border-top: 16px solid rgba(0, 30, 30, 0.7); border-left: none; border-right: 16px solid transparent; border-bottom: none; } -.feed-entries { margin-left: 0px; } -.feed-entry { position: relative; margin-bottom: 18px; } -.feed-date { float: left; height: 100%; margin-right: 14px; height: 100%;} -.feed-month { color: #447281; font-size: 18px; font-weight: bold; text-transform:uppercase;} -.feed-day { background: #15A9CE; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; color: #EFF2F5; font-weight: bold; font-size: 24px; text-align: center; line-height: 26px;} -.feed-year { color: #447281; font-size: 16px; font-weight: bold; } -.feed-title { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 18px; font-weight: 400; line-height: 20px; } -.feed-title a { color: #15A9CE; } -.feed-title a:hover { color: #447281; text-decoration: none; } -.feed-author { font-size: 11px; color: #888888;} -.feed-body { margin-bottom: 14px;} -.news-item { margin-bottom: 14px;} -.news-date { display: inline; font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 14px; font-weight: 500; line-height: 16px; color: #15A9CE; } -.news-author { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 12px; font-weight: 500; line-height: 15px; color: #447281; } -.news-title { font-family: "Source Sans Pro", "Helvetica Neue", sans-serif; font-size: 18px; font-weight: 400; line-height: 20px; margin-bottom: 4px;} -.news-title a { color: #447281; } -.news-title a:hover { color: #15A9CE; text-decoration: none; } - -.footer { padding-top: 15px; clear: both; width: 100%; color: #ffffff; background: #15A9CE; } -.footer ul { float: left; margin: 0; padding: 10px 2% 20px 0; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; width: 22%; list-style: none; } -.footer a {text-decoration: none;color: #ffffff; font-size: 12px;} -.footer a:hover {text-decoration: underline;} -.footer ul:last-child { padding-right: 0; } -.footer ul li a { text-decoration: none; color: #ffffff; font-size: 12px; } -.footer ul li a:hover { text-decoration: underline; } -.footer ul li h5 { color: #ffffff; margin-bottom: 10px; padding-bottom: 10px; line-height: 20px; border-bottom:1px solid rgba(255,255,255,0.5); } -.footer ul li h5 a { font-size: 14px; opacity: 1;} -.footer .copyright { font-size: 12px; border-top:1px solid rgba(255,255,255,0.5); clear: both; padding: 10px 0 20px; } -.footer .license { float: right; font-size: 12px; } diff --git a/akka-docs-dev/_sphinx/themes/akka/static/contentsFix.js b/akka-docs-dev/_sphinx/themes/akka/static/contentsFix.js deleted file mode 100644 index e729663ce9..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/contentsFix.js +++ /dev/null @@ -1,10 +0,0 @@ -jQuery(document).ready(function($) { - - $("#toc ul").each(function(){ - var elem = $(this); - if (elem.children().length == 0) { - $(".contents-title").css("display","none"); - } - }); - -}); \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/docs.css b/akka-docs-dev/_sphinx/themes/akka/static/docs.css deleted file mode 100644 index e1c5d9f041..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/docs.css +++ /dev/null @@ -1,222 +0,0 @@ -body { position: relative; color: #0B5567;} -a { color: #15A9CE; } -a:hover { color: #15A9CE; text-decoration: underline; } -.navbar { margin-bottom: 18px; } -.navbar-logo { visibility: visible; float: left; padding-top: 0px; } -.main { position: relative; height: auto; margin-top: -18px; overflow: auto; background: #15A9CE;} -.page-title { position: relative; top: 24px; font-family: 'Source Sans Pro', sans-serif; font-size: 24px; font-weight: 400; color: rgba(255, 255, 255, 1); width: 840px;} -.main-container { background: #ffffff; min-height: 600px; padding-top: 20px; margin-top: 28px; } -.pdf-link { float: right; height: 40px; margin-bottom: -15px; margin-top: -5px; } -.breadcrumb { height: 18px; } -.breadcrumb li { float: right; } -.breadcrumb li a { color: #447281; } -.breadcrumb li a:hover { color: #15A9CE; text-decoration: none; } -.breadcrumb li:last-child { float: left; font-weight: bold; } -.contents-title { font-weight: bold; font-size: 18px; line-height: 27px; margin-bottom: 6px; color: #0d2428; text-shadow:0 1px 0 #f0fafc; } -div#toc { margin-left: -16px; } -div#toc ul { list-style: none; margin: 0 0 5px 16px; } -div#toc ul li { padding-bottom: 8px; line-height: 105%; font-weight: bold; width: 100%; } -div#toc ul ul { list-style: disc; } -div#toc ul ul ul { list-style: square; } -div#toc ul li ul li { padding-bottom: 0px; line-height: 18px; font-weight: normal; } -div#scroller-anchor { width: inherit; } -div#scroller { width: inherit; } -p { padding-top: 4px; font-size: 14px; } -h1 {color: #15A9CE; } -h2 { padding-top: 14px; padding-bottom: 4px; margin-bottom: 2px; border-bottom: solid 1px rgba(0, 0, 0, 0.15); color: #0B5567; } -h2 a { color: #0B5567; } -h2 a:hover { color: #447281; } -h2 .pre { font-size: 20px; } -h3 { padding-top: 10px; color: #0B5567; } -h3 a { color: #0B5567; } -h3 a:hover { } -h3 .pre { font-size: 16px; } -h4 { padding-top: 6px; font-size: 16px; } -h4 a { color: #0B5567; } -h4 a:hover { text-shadow:0 2px 0 #0B5567; } -h5 { text-transform: uppercase; font-size: 14px; padding-top: 6px; color: #0B5567;} -strong {color: #0B5567; } -/*.footer-bg { overflow: auto; background:url('{{ site.baseurl }}/resources/images/dark-blue-bg.png') repeat; height: 100%; }*/ - -.toctree-l1 { font-weight: bold; font-size: 14px; padding-top: 4px;} -.toctree-l1 a { color: #15384e; } -.toctree-l1 a:hover { color: #15A9CE; text-decoration: none; } -.toctree-l2 { font-weight: normal; list-style: square; } -.toctree-l2 a { color: #447281; } -.toctree-l2 a:hover { color: #15A9CE; text-decoration: none; } - -.topic-title { - color: rgba(0, 0, 0, 0.6); - text-shadow: 0 1px 0 rgba(255, 255, 255, .7); - margin-bottom: 6px; - font-size: 24px; - font-weight: bold; - line-height: 36px; -} - -.admonition { - background-image: none; - background-color: #fdf5d9; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - padding: 14px; - border-color: #73cbe2; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - margin-bottom: 18px; - position: relative; - padding: 7px 15px; - color: #ffffff; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#73cbe2), to(#15a9ce)); - background-image: -moz-linear-gradient(top, #73cbe2, #15a9ce); - background-image: -ms-linear-gradient(top, #73cbe2, #15a9ce); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #73cbe2), color-stop(100%, #15a9ce)); - background-image: -webkit-linear-gradient(top, #73cbe2, #15a9ce); - background-image: -o-linear-gradient(top, #73cbe2, #15a9ce); - background-image: linear-gradient(top, #73cbe2, #15a9ce); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#73cbe2', endColorstr='#15a9ce', GradientType=0); - border-color: #15a9ce #15a9ce #E4C652; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-width: 1px; - border-style: solid; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} - -.warning { - background-image: none; - background-color: #e25758; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - padding: 14px; - border-color: #f06565; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - margin-bottom: 18px; - position: relative; - padding: 7px 15px; - color: #ffffff; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#f06565), to(#e25758)); - background-image: -moz-linear-gradient(top, #f06565, #e25758); - background-image: -ms-linear-gradient(top, #f06565, #e25758); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f06565), color-stop(100%, #e25758)); - background-image: -webkit-linear-gradient(top, #f06565, #e25758); - background-image: -o-linear-gradient(top, #f06565, #e25758); - background-image: linear-gradient(top, #f06565, #e25758); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f06565', endColorstr='#e25758', GradientType=0); - border-color: #15a9ce #e25758 #E4C652; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-width: 1px; - border-style: solid; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} -.admonition a { - color: #0B5567; -} -.admonition a:hover { - text-decoration: underline; -} -.admonition p.admonition-title { - color: #ffffff; - margin-bottom: 6px; - font-size: 16px; - font-weight: bold; - line-height: 20px; -} - -.topic { - background-image: none; - background-color: #fdf5d9; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - padding: 14px; - border-color: #def1f4; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - margin-bottom: 18px; - position: relative; - padding: 7px 15px; - color: #404040; - background-repeat: repeat-x; - background-image: -khtml-gradient(linear, left top, left bottom, from(#def1f4), to(#c1dfe6)); - background-image: -moz-linear-gradient(top, #def1f4, #c1dfe6); - background-image: -ms-linear-gradient(top, #def1f4, #c1dfe6); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #def1f4), color-stop(100%, #c1dfe6)); - background-image: -webkit-linear-gradient(top, #def1f4, #c1dfe6); - background-image: -o-linear-gradient(top, #def1f4, #c1dfe6); - background-image: linear-gradient(top, #def1f4, #c1dfe6); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#def1f4', endColorstr='#c1dfe6', GradientType=0); - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - border-color: #c1dfe6 #c1dfe6 #E4C652; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-width: 1px; - border-style: solid; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} - -.pre { padding: 1px 2px; color: #008FA9; background-color: #EFF2F5; border: 1px solid #DDDEDF; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } -.footer h5 { text-transform: none; } - - -.section-marker { position: absolute; width: 1em; margin-left: -1em; display: block; text-decoration: none; visibility: hidden; text-align: center; font-weight: normal; } -.section-marker:hover { text-decoration: none; } -.section h2:hover > a,.section h3:hover > a,.section h4:hover > a,.section h5:hover > a { visibility: visible; } - - -/* - * Used when browsing 2.3.12 yet 2.4.x is out already. - * This is more critical than browsing 2.3.10 and 2.3.11 is latest (the default color). - */ -#floaty-warning .warning { - background-color: rgb(227, 88, 89); -} - -#floaty-warning a { - color: white !important; - font-weight: bold; - text-decoration: underline; -} - -#floaty-warning button { - border-radius: 4px; - border: none; - margin: 0; - padding: 1em 2em; - font-weight: bold; - color: white; -} - -#floaty-warning button { - background-color: #89CDDE; -} -#floaty-warning button:hover { - background-color: #74DDF7; -} - -#floaty-warning.warning button { - background-color: #F98D8D; -} -#floaty-warning.warning button:hover { - background-color: #F77979; -} - -#close-floaty-window { - padding: 1em; - margin-top: 1em; -} \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/effects.core.js b/akka-docs-dev/_sphinx/themes/akka/static/effects.core.js deleted file mode 100644 index ed4fd37741..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/effects.core.js +++ /dev/null @@ -1,509 +0,0 @@ -/* - * jQuery UI Effects 1.5.3 - * - * Copyright (c) 2008 Aaron Eisenberger (aaronchi@gmail.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Effects/ - */ -;(function($) { - -$.effects = $.effects || {}; //Add the 'effects' scope - -$.extend($.effects, { - save: function(el, set) { - for(var i=0;i'); - var wrapper = el.parent(); - if (el.css('position') == 'static'){ - wrapper.css({position: 'relative'}); - el.css({position: 'relative'}); - } else { - var top = el.css('top'); if(isNaN(parseInt(top))) top = 'auto'; - var left = el.css('left'); if(isNaN(parseInt(left))) left = 'auto'; - wrapper.css({ position: el.css('position'), top: top, left: left, zIndex: el.css('z-index') }).show(); - el.css({position: 'relative', top:0, left:0}); - } - wrapper.css(props); - return wrapper; - }, - removeWrapper: function(el) { - if (el.parent().attr('id') == 'fxWrapper') - return el.parent().replaceWith(el); - return el; - }, - setTransition: function(el, list, factor, val) { - val = val || {}; - $.each(list,function(i, x){ - unit = el.cssUnit(x); - if (unit[0] > 0) val[x] = unit[0] * factor + unit[1]; - }); - return val; - }, - animateClass: function(value, duration, easing, callback) { - - var cb = (typeof easing == "function" ? easing : (callback ? callback : null)); - var ea = (typeof easing == "object" ? easing : null); - - return this.each(function() { - - var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || ''; - if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */ - if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; } - - //Let's get a style offset - var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle)); - if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove); - var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle)); - if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove); - - // The main function to form the object for animation - for(var n in newStyle) { - if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */ - && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */ - && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */ - && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */ - && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */ - ) offset[n] = newStyle[n]; - } - - that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object - // Change style attribute back to original. For stupid IE, we need to clear the damn object. - if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr); - if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove); - if(cb) cb.apply(this, arguments); - }); - - }); - } -}); - -//Extend the methods of jQuery -$.fn.extend({ - //Save old methods - _show: $.fn.show, - _hide: $.fn.hide, - __toggle: $.fn.toggle, - _addClass: $.fn.addClass, - _removeClass: $.fn.removeClass, - _toggleClass: $.fn.toggleClass, - // New ec methods - effect: function(fx,o,speed,callback) { - return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: o || {}, duration: speed, callback: callback }) : null; - }, - show: function() { - if(!arguments[0] || (arguments[0].constructor == Number || /(slow|normal|fast)/.test(arguments[0]))) - return this._show.apply(this, arguments); - else { - var o = arguments[1] || {}; o['mode'] = 'show'; - return this.effect.apply(this, [arguments[0], o, arguments[2] || o.duration, arguments[3] || o.callback]); - } - }, - hide: function() { - if(!arguments[0] || (arguments[0].constructor == Number || /(slow|normal|fast)/.test(arguments[0]))) - return this._hide.apply(this, arguments); - else { - var o = arguments[1] || {}; o['mode'] = 'hide'; - return this.effect.apply(this, [arguments[0], o, arguments[2] || o.duration, arguments[3] || o.callback]); - } - }, - toggle: function(){ - if(!arguments[0] || (arguments[0].constructor == Number || /(slow|normal|fast)/.test(arguments[0])) || (arguments[0].constructor == Function)) - return this.__toggle.apply(this, arguments); - else { - var o = arguments[1] || {}; o['mode'] = 'toggle'; - return this.effect.apply(this, [arguments[0], o, arguments[2] || o.duration, arguments[3] || o.callback]); - } - }, - addClass: function(classNames,speed,easing,callback) { - return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); - }, - removeClass: function(classNames,speed,easing,callback) { - return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); - }, - toggleClass: function(classNames,speed,easing,callback) { - return speed ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames); - }, - morph: function(remove,add,speed,easing,callback) { - return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); - }, - switchClass: function() { - return this.morph.apply(this, arguments); - }, - // helper functions - cssUnit: function(key) { - var style = this.css(key), val = []; - $.each( ['em','px','%','pt'], function(i, unit){ - if(style.indexOf(unit) > 0) - val = [parseFloat(style), unit]; - }); - return val; - } -}); - -/* - * jQuery Color Animations - * Copyright 2007 John Resig - * Released under the MIT and GPL licenses. - */ - -// We override the animation for all of these color styles -jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){ - jQuery.fx.step[attr] = function(fx){ - if ( fx.state == 0 ) { - fx.start = getColor( fx.elem, attr ); - fx.end = getRGB( fx.end ); - } - - fx.elem.style[attr] = "rgb(" + [ - Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0), - Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0), - Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0) - ].join(",") + ")"; - } -}); - -// Color Conversion functions from highlightFade -// By Blair Mitchelmore -// http://jquery.offput.ca/highlightFade/ - -// Parse strings looking for color tuples [255,255,255] -function getRGB(color) { - var result; - - // Check if we're already dealing with an array of colors - if ( color && color.constructor == Array && color.length == 3 ) - return color; - - // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) - return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; - - // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) - return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; - - // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) - return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; - - // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) - return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; - - // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) - return colors['transparent'] - - // Otherwise, we're most likely dealing with a named color - return colors[jQuery.trim(color).toLowerCase()]; -} - -function getColor(elem, attr) { - var color; - - do { - color = jQuery.curCSS(elem, attr); - - // Keep going until we find an element that has color, or we hit the body - if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") ) - break; - - attr = "backgroundColor"; - } while ( elem = elem.parentNode ); - - return getRGB(color); -}; - -// Some named colors to work with -// From Interface by Stefan Petre -// http://interface.eyecon.ro/ - -var colors = { - aqua:[0,255,255], - azure:[240,255,255], - beige:[245,245,220], - black:[0,0,0], - blue:[0,0,255], - brown:[165,42,42], - cyan:[0,255,255], - darkblue:[0,0,139], - darkcyan:[0,139,139], - darkgrey:[169,169,169], - darkgreen:[0,100,0], - darkkhaki:[189,183,107], - darkmagenta:[139,0,139], - darkolivegreen:[85,107,47], - darkorange:[255,140,0], - darkorchid:[153,50,204], - darkred:[139,0,0], - darksalmon:[233,150,122], - darkviolet:[148,0,211], - fuchsia:[255,0,255], - gold:[255,215,0], - green:[0,128,0], - indigo:[75,0,130], - khaki:[240,230,140], - lightblue:[173,216,230], - lightcyan:[224,255,255], - lightgreen:[144,238,144], - lightgrey:[211,211,211], - lightpink:[255,182,193], - lightyellow:[255,255,224], - lime:[0,255,0], - magenta:[255,0,255], - maroon:[128,0,0], - navy:[0,0,128], - olive:[128,128,0], - orange:[255,165,0], - pink:[255,192,203], - purple:[128,0,128], - violet:[128,0,128], - red:[255,0,0], - silver:[192,192,192], - white:[255,255,255], - yellow:[255,255,0], - transparent: [255,255,255] -}; - -/* - * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ - * - * Uses the built in easing capabilities added In jQuery 1.1 - * to offer multiple easing options - * - * TERMS OF USE - jQuery Easing - * - * Open source under the BSD License. - * - * Copyright © 2008 George McGinley Smith - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -// t: current time, b: begInnIng value, c: change In value, d: duration -jQuery.easing['jswing'] = jQuery.easing['swing']; - -jQuery.extend( jQuery.easing, -{ - def: 'easeOutQuad', - swing: function (x, t, b, c, d) { - //alert(jQuery.easing.default); - return jQuery.easing[jQuery.easing.def](x, t, b, c, d); - }, - easeInQuad: function (x, t, b, c, d) { - return c*(t/=d)*t + b; - }, - easeOutQuad: function (x, t, b, c, d) { - return -c *(t/=d)*(t-2) + b; - }, - easeInOutQuad: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t + b; - return -c/2 * ((--t)*(t-2) - 1) + b; - }, - easeInCubic: function (x, t, b, c, d) { - return c*(t/=d)*t*t + b; - }, - easeOutCubic: function (x, t, b, c, d) { - return c*((t=t/d-1)*t*t + 1) + b; - }, - easeInOutCubic: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t + b; - return c/2*((t-=2)*t*t + 2) + b; - }, - easeInQuart: function (x, t, b, c, d) { - return c*(t/=d)*t*t*t + b; - }, - easeOutQuart: function (x, t, b, c, d) { - return -c * ((t=t/d-1)*t*t*t - 1) + b; - }, - easeInOutQuart: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t*t + b; - return -c/2 * ((t-=2)*t*t*t - 2) + b; - }, - easeInQuint: function (x, t, b, c, d) { - return c*(t/=d)*t*t*t*t + b; - }, - easeOutQuint: function (x, t, b, c, d) { - return c*((t=t/d-1)*t*t*t*t + 1) + b; - }, - easeInOutQuint: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; - return c/2*((t-=2)*t*t*t*t + 2) + b; - }, - easeInSine: function (x, t, b, c, d) { - return -c * Math.cos(t/d * (Math.PI/2)) + c + b; - }, - easeOutSine: function (x, t, b, c, d) { - return c * Math.sin(t/d * (Math.PI/2)) + b; - }, - easeInOutSine: function (x, t, b, c, d) { - return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; - }, - easeInExpo: function (x, t, b, c, d) { - return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; - }, - easeOutExpo: function (x, t, b, c, d) { - return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; - }, - easeInOutExpo: function (x, t, b, c, d) { - if (t==0) return b; - if (t==d) return b+c; - if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; - return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; - }, - easeInCirc: function (x, t, b, c, d) { - return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; - }, - easeOutCirc: function (x, t, b, c, d) { - return c * Math.sqrt(1 - (t=t/d-1)*t) + b; - }, - easeInOutCirc: function (x, t, b, c, d) { - if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; - return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; - }, - easeInElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; - }, - easeOutElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; - }, - easeInOutElastic: function (x, t, b, c, d) { - var s=1.70158;var p=0;var a=c; - if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); - if (a < Math.abs(c)) { a=c; var s=p/4; } - else var s = p/(2*Math.PI) * Math.asin (c/a); - if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; - return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; - }, - easeInBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - return c*(t/=d)*t*((s+1)*t - s) + b; - }, - easeOutBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; - }, - easeInOutBack: function (x, t, b, c, d, s) { - if (s == undefined) s = 1.70158; - if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; - return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; - }, - easeInBounce: function (x, t, b, c, d) { - return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; - }, - easeOutBounce: function (x, t, b, c, d) { - if ((t/=d) < (1/2.75)) { - return c*(7.5625*t*t) + b; - } else if (t < (2/2.75)) { - return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; - } else if (t < (2.5/2.75)) { - return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; - } else { - return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; - } - }, - easeInOutBounce: function (x, t, b, c, d) { - if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; - return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; - } -}); - -/* - * - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright © 2001 Robert Penner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -})(jQuery); \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/effects.highlight.js b/akka-docs-dev/_sphinx/themes/akka/static/effects.highlight.js deleted file mode 100644 index c9c332522b..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/effects.highlight.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * jQuery UI Effects Highlight @VERSION - * - * Copyright (c) 2008 Aaron Eisenberger (aaronchi@gmail.com) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * effects.core.js - */ -(function($) { - -$.effects.highlight = function(o) { - - return this.queue(function() { - - // Create element - var el = $(this), props = ['backgroundImage','backgroundColor','opacity']; - - // Set options - var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode - var color = o.options.color || "#ffff99"; // Default highlight color - var oldColor = "#f2f2eb"; - - // Adjust - $.effects.save(el, props); el.show(); // Save & Show - el.css({backgroundImage: 'none', backgroundColor: color}); // Shift - - // Animation - var animation = {backgroundColor: oldColor }; - if (mode == "hide") animation['opacity'] = 0; - - // Animate - el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { - if(mode == "hide") el.hide(); - $.effects.restore(el, props); - if (mode == "show" && jQuery.browser.msie) this.style.removeAttribute('filter'); - if(o.callback) o.callback.apply(this, arguments); - el.dequeue(); - }}); - - }); - -}; - -})(jQuery); \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/ga.js b/akka-docs-dev/_sphinx/themes/akka/static/ga.js deleted file mode 100644 index 730ea9160c..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/ga.js +++ /dev/null @@ -1,43 +0,0 @@ -// check to see if this document is on the akka.io server. If so, google analytics and marketo -if (/akka\.io/.test(document.domain)) { - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-21117439-1']); - _gaq.push(['_setDomainName', 'akka.io']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-23127719-1', 'typesafe.com', {'allowLinker': true, 'name': 'tsTracker'}); - ga('tsTracker.require', 'linker'); - ga('tsTracker.linker:autoLink', ['typesafe.com','playframework.com','scala-lang.org','scaladays.org','spray.io','akka.io','scala-sbt.org','scala-ide.org']); - ga('tsTracker.send', 'pageview'); - - (function() { - var didInit = false; - function initMunchkin() { - if(didInit === false) { - didInit = true; - Munchkin.init('558-NCX-702'); - } - } - var s = document.createElement('script'); - s.type = 'text/javascript'; - s.async = true; - s.src = '//munchkin.marketo.net/munchkin.js'; - s.onreadystatechange = function() { - if (this.readyState == 'complete' || this.readyState == 'loaded') { - initMunchkin(); - } - }; - s.onload = initMunchkin; - document.getElementsByTagName('head')[0].appendChild(s); - })(); -} \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/highlightCode.js b/akka-docs-dev/_sphinx/themes/akka/static/highlightCode.js deleted file mode 100644 index 401b9ec471..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/highlightCode.js +++ /dev/null @@ -1,13 +0,0 @@ -jQuery(document).ready(function($) { - if (typeof disableStyleCode != "undefined") { - return; - } - var a = false; - $("pre").each(function() { - if (!$(this).hasClass("prettyprint")) { - $(this).addClass("prettyprint lang-scala linenums"); - a = true - } - }); - if (a) { prettyPrint() } -}); diff --git a/akka-docs-dev/_sphinx/themes/akka/static/jquery.js b/akka-docs-dev/_sphinx/themes/akka/static/jquery.js deleted file mode 100644 index ee0233703d..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/jquery.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.1 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; -f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() -{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/themes/akka/static/logo-small.png b/akka-docs-dev/_sphinx/themes/akka/static/logo-small.png deleted file mode 100644 index 2ad5096d3c6a590fcc1f71836c275afd56cf8cef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 946 zcmeAS@N?(olHy`uVBq!ia0y~yV6bOkV36WqV_;w`x7>1ufq_A?#5JNMI6tkVJh3R1 z!7(L2DOJHUH!(dmC^a#qvhZZ84Fdynh^LEVNX4zB1O>4_>`WSK8&sYh=uo-IA-X=D zg(=0ig3*CN(8XXePs5c;mBkO=CA8eyEYKnEaP-Z>H~bDU4i~r@7#7Jf?MnGuuhJmL zb0W#(4cm+-)jDiKPwN^O7IlWpXk7dwfA&6K01p#efYgz2hdytSvk^Q8IYJav8IJr_ zFyoHOFi-M4xPV2GfjdJ(m*I%C!K7aeM;II!cFa4=db{!HB=sFSNhu*Ls-6nMmfF9S zSGSA#E7aKu_%poHbUF8{$73hIWry^_RH-#R#tvl?7bdhNPCmxKlp*r)G$)e;tJ++h zdHrz;j{|qh$E{ZUQL$QB&8BTGdl2V|wnR?Bh|r{l^?c1A7rtUms1Zx@($^?(n8eQz z^t$l}L&zV7S@&E@?56BvIJ@t|o4$9_H3{}Xo@ossR`1-kPJUBnwO-RweBhcuqKgp2 z_6-+ms+l^23E@z9juW|Uk@@b(b&nc^@ZJ({Q|E90xnuHuKH)Q=49*I&ML-L zFPYA458x?hxbTTJBsbCV@p6WKDb@_%qlQtx0=XENwj>|*U~zU7Q4i3PeK_4K?*OL- zllg*>ryNmp!`i(xm-hAPX@7gX4B>K zA5Sh<3iziinEWeCt!c}gjFQqrU#D8RF6W8aB%~^8VWe+vyRC(1zxXPjMTce|53m)v z^Q5)Jf0t<0MSh1gb>+=fpI2%>mMl{~;I!&@qsN0S&swJL5Nt4--*O<eN4T?l7FaIC)-Cy9^Hl0|SGntDnm{r-UW| DleUi| diff --git a/akka-docs-dev/_sphinx/themes/akka/static/pdf-icon.png b/akka-docs-dev/_sphinx/themes/akka/static/pdf-icon.png deleted file mode 100644 index 203ecad073537158e7b3899aa5deb2690416de81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15170 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 diff --git a/akka-docs-dev/_sphinx/themes/akka/static/pdf-scala-icon.png b/akka-docs-dev/_sphinx/themes/akka/static/pdf-scala-icon.png deleted file mode 100644 index 1210d021add83eafe13de5e728b2e9f8ad9cea97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19064 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 z 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.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p[class*="span"]{float:left;margin-left:2.127659574%;} -.row-fluid>[class*="span"]:first-child{margin-left:0;} -.row-fluid .span1{width:6.382978723%;} -.row-fluid .span2{width:14.89361702%;} -.row-fluid .span3{width:23.404255317%;} -.row-fluid .span4{width:31.914893614%;} -.row-fluid .span5{width:40.425531911%;} -.row-fluid .span6{width:48.93617020799999%;} -.row-fluid .span7{width:57.446808505%;} -.row-fluid .span8{width:65.95744680199999%;} -.row-fluid .span9{width:74.468085099%;} -.row-fluid .span10{width:82.97872339599999%;} -.row-fluid .span11{width:91.489361693%;} -.row-fluid .span12{width:99.99999998999999%;} -.container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";} -.container:after{clear:both;} -.container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";} -.container-fluid:after{clear:both;} -p{margin:0 0 9px;font-family:"Source Sans Pro", "Helvetica Neue",sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;} -.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;} -h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;} -h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;} -h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;} -h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;} -h4,h5,h6{line-height:18px;} -h4{font-size:14px;}h4 small{font-size:12px;} -h5{font-size:12px;} -h6{font-size:11px;color:#999999;text-transform:uppercase;} -.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;} -.page-header h1{line-height:1;} -ul,ol{padding:0;margin:0 0 9px 25px;} -ul ul,ul ol,ol ol,ol ul{margin-bottom:0;} -ul{list-style:disc;} -ol{list-style:decimal;} -li{line-height:18px;} -ul.unstyled{margin-left:0;list-style:none;} -dl{margin-bottom:18px;} -dt,dd{line-height:18px;} -dt{font-weight:bold;} -dd{margin-left:9px;} -hr{margin:18px 0;border:0;border-top:1px solid #e5e5e5;border-bottom:1px solid #ffffff;} -strong{font-weight:bold;} -em{font-style:italic;} -.muted{color:#999999;} -abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;} -blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;} -blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';} -blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;} -q:before,q:after,blockquote:before,blockquote:after{content:"";} -address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;} -small{font-size:100%;} -cite{font-style:normal;} -code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} -code{padding:1px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;} -pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;/*white-space:pre;white-space:pre-wrap*/;word-break:break-all;}pre.prettyprint{margin-bottom:18px;} -pre code{padding:0;background-color:transparent;} -form{margin:0 0 18px;} -fieldset{padding:0;margin:0;border:0;} -legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;} -label,input,button,select,textarea{font-family:"Source Sans Pro", "Helvetica Neue", sans-serif;font-size:13px;font-weight:normal;line-height:18px;} -label{display:block;margin-bottom:5px;color:#333333;} -input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} -.uneditable-textarea{width:auto;height:auto;} -label input,label textarea,label select{display:block;} -input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:0;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} -input[type="file"]{padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} -input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto;} -select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px;} -select{width:220px;background-color:#ffffff;} -select[multiple],select[size]{height:auto;} -input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} -textarea{height:auto;} -input[type="hidden"]{display:none;} -.radio,.checkbox{padding-left:18px;} -.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;} -.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;} -.radio.inline,.checkbox.inline{display:inline-block;margin-bottom:0;vertical-align:middle;} -.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;} -.controls>.radio.inline:first-child,.controls>.checkbox.inline:first-child{padding-top:0;} -input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;} -input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;} -input[type="file"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} -.input-mini{width:60px;} -.input-small{width:90px;} -.input-medium{width:150px;} -.input-large{width:210px;} -.input-xlarge{width:270px;} -.input-xxlarge{width:530px;} -input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;} -input.span1,textarea.span1,.uneditable-input.span1{width:50px;} -input.span2,textarea.span2,.uneditable-input.span2{width:130px;} -input.span3,textarea.span3,.uneditable-input.span3{width:210px;} -input.span4,textarea.span4,.uneditable-input.span4{width:290px;} -input.span5,textarea.span5,.uneditable-input.span5{width:370px;} -input.span6,textarea.span6,.uneditable-input.span6{width:450px;} -input.span7,textarea.span7,.uneditable-input.span7{width:530px;} -input.span8,textarea.span8,.uneditable-input.span8{width:610px;} -input.span9,textarea.span9,.uneditable-input.span9{width:690px;} -input.span10,textarea.span10,.uneditable-input.span10{width:770px;} -input.span11,textarea.span11,.uneditable-input.span11{width:850px;} -input.span12,textarea.span12,.uneditable-input.span12{width:930px;} -input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;} -.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;} -.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e;} -.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;} -.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;} -.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392;} -.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;} -.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;} -.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b;} -.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;} -input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;} -.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;} -.uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} -:-moz-placeholder{color:#999999;} -::-webkit-input-placeholder{color:#999999;} -.help-block{margin-top:5px;margin-bottom:0;color:#999999;} -.help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px;} -.input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";} -.input-prepend:after,.input-append:after{clear:both;} -.input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2;} -.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;} -.input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} -.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;} -.input-prepend .add-on{*margin-top:1px;} -.input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} -.input-append .uneditable-input{border-right-color:#ccc;} -.input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} -.input-append input:first-child{*margin-left:-160px;}.input-append input:first-child+.add-on{*margin-left:-21px;} -.search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;} -.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;} -.form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block;} -.form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle;} -.control-group{margin-bottom:9px;} -.form-horizontal legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate;} -.form-horizontal .control-group{margin-bottom:18px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";} -.form-horizontal .control-group:after{clear:both;} -.form-horizontal .control-group>label{float:left;width:140px;padding-top:5px;text-align:right;} -.form-horizontal .controls{margin-left:160px;} -.form-horizontal .form-actions{padding-left:160px;} -table{max-width:100%;border-collapse:collapse;border-spacing:0;} -.table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;border-top:1px solid #ddd;} -.table th{font-weight:bold;vertical-align:bottom;} -.table td{vertical-align:top;} -.table thead:first-child tr th,.table thead:first-child tr td{border-top:0;} -.table tbody+tbody{border-top:2px solid #ddd;} -.table-condensed th,.table-condensed td{padding:4px 5px;} -.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;} -.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;} -.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;} -.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;} -.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;} -.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;} -.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;} -table .span1{float:none;width:44px;margin-left:0;} -table .span2{float:none;width:124px;margin-left:0;} -table .span3{float:none;width:204px;margin-left:0;} -table .span4{float:none;width:284px;margin-left:0;} -table .span5{float:none;width:364px;margin-left:0;} -table .span6{float:none;width:444px;margin-left:0;} -table .span7{float:none;width:524px;margin-left:0;} -table .span8{float:none;width:604px;margin-left:0;} -table .span9{float:none;width:684px;margin-left:0;} -table .span10{float:none;width:764px;margin-left:0;} -table .span11{float:none;width:844px;margin-left:0;} -table .span12{float:none;width:924px;margin-left:0;} -[class^="icon-"]{display:inline-block;width:14px;height:14px;vertical-align:text-top;background-image:url(../img/glyphicons-halflings.png);background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}[class^="icon-"]:last-child{*margin-left:0;} -.icon-white{background-image:url(../img/glyphicons-halflings-white.png);} -.icon-glass{background-position:0 0;} -.icon-music{background-position:-24px 0;} -.icon-search{background-position:-48px 0;} -.icon-envelope{background-position:-72px 0;} -.icon-heart{background-position:-96px 0;} -.icon-star{background-position:-120px 0;} -.icon-star-empty{background-position:-144px 0;} -.icon-user{background-position:-168px 0;} -.icon-film{background-position:-192px 0;} -.icon-th-large{background-position:-216px 0;} -.icon-th{background-position:-240px 0;} -.icon-th-list{background-position:-264px 0;} -.icon-ok{background-position:-288px 0;} -.icon-remove{background-position:-312px 0;} -.icon-zoom-in{background-position:-336px 0;} -.icon-zoom-out{background-position:-360px 0;} -.icon-off{background-position:-384px 0;} -.icon-signal{background-position:-408px 0;} -.icon-cog{background-position:-432px 0;} -.icon-trash{background-position:-456px 0;} -.icon-home{background-position:0 -24px;} -.icon-file{background-position:-24px -24px;} -.icon-time{background-position:-48px -24px;} -.icon-road{background-position:-72px -24px;} -.icon-download-alt{background-position:-96px -24px;} -.icon-download{background-position:-120px -24px;} -.icon-upload{background-position:-144px -24px;} -.icon-inbox{background-position:-168px -24px;} -.icon-play-circle{background-position:-192px -24px;} -.icon-repeat{background-position:-216px -24px;} -.icon-refresh{background-position:-240px -24px;} -.icon-list-alt{background-position:-264px -24px;} -.icon-lock{background-position:-287px -24px;} -.icon-flag{background-position:-312px -24px;} -.icon-headphones{background-position:-336px -24px;} -.icon-volume-off{background-position:-360px -24px;} -.icon-volume-down{background-position:-384px -24px;} -.icon-volume-up{background-position:-408px -24px;} -.icon-qrcode{background-position:-432px -24px;} -.icon-barcode{background-position:-456px -24px;} -.icon-tag{background-position:0 -48px;} -.icon-tags{background-position:-25px -48px;} -.icon-book{background-position:-48px -48px;} -.icon-bookmark{background-position:-72px -48px;} -.icon-print{background-position:-96px -48px;} -.icon-camera{background-position:-120px -48px;} -.icon-font{background-position:-144px -48px;} -.icon-bold{background-position:-167px -48px;} -.icon-italic{background-position:-192px -48px;} -.icon-text-height{background-position:-216px -48px;} -.icon-text-width{background-position:-240px -48px;} -.icon-align-left{background-position:-264px -48px;} -.icon-align-center{background-position:-288px -48px;} -.icon-align-right{background-position:-312px -48px;} -.icon-align-justify{background-position:-336px -48px;} -.icon-list{background-position:-360px -48px;} -.icon-indent-left{background-position:-384px -48px;} -.icon-indent-right{background-position:-408px -48px;} -.icon-facetime-video{background-position:-432px -48px;} -.icon-picture{background-position:-456px -48px;} -.icon-pencil{background-position:0 -72px;} -.icon-map-marker{background-position:-24px -72px;} -.icon-adjust{background-position:-48px -72px;} -.icon-tint{background-position:-72px -72px;} -.icon-edit{background-position:-96px -72px;} -.icon-share{background-position:-120px -72px;} -.icon-check{background-position:-144px -72px;} -.icon-move{background-position:-168px -72px;} -.icon-step-backward{background-position:-192px -72px;} -.icon-fast-backward{background-position:-216px -72px;} -.icon-backward{background-position:-240px -72px;} -.icon-play{background-position:-264px -72px;} -.icon-pause{background-position:-288px -72px;} -.icon-stop{background-position:-312px -72px;} -.icon-forward{background-position:-336px -72px;} -.icon-fast-forward{background-position:-360px -72px;} -.icon-step-forward{background-position:-384px -72px;} -.icon-eject{background-position:-408px -72px;} -.icon-chevron-left{background-position:-432px -72px;} -.icon-chevron-right{background-position:-456px -72px;} -.icon-plus-sign{background-position:0 -96px;} -.icon-minus-sign{background-position:-24px -96px;} -.icon-remove-sign{background-position:-48px -96px;} -.icon-ok-sign{background-position:-72px -96px;} -.icon-question-sign{background-position:-96px -96px;} -.icon-info-sign{background-position:-120px -96px;} -.icon-screenshot{background-position:-144px -96px;} -.icon-remove-circle{background-position:-168px -96px;} -.icon-ok-circle{background-position:-192px -96px;} -.icon-ban-circle{background-position:-216px -96px;} -.icon-arrow-left{background-position:-240px -96px;} -.icon-arrow-right{background-position:-264px -96px;} -.icon-arrow-up{background-position:-289px -96px;} -.icon-arrow-down{background-position:-312px -96px;} -.icon-share-alt{background-position:-336px -96px;} -.icon-resize-full{background-position:-360px -96px;} -.icon-resize-small{background-position:-384px -96px;} -.icon-plus{background-position:-408px -96px;} -.icon-minus{background-position:-433px -96px;} -.icon-asterisk{background-position:-456px -96px;} -.icon-exclamation-sign{background-position:0 -120px;} -.icon-gift{background-position:-24px -120px;} -.icon-leaf{background-position:-48px -120px;} -.icon-fire{background-position:-72px -120px;} -.icon-eye-open{background-position:-96px -120px;} -.icon-eye-close{background-position:-120px -120px;} -.icon-warning-sign{background-position:-144px -120px;} -.icon-plane{background-position:-168px -120px;} -.icon-calendar{background-position:-192px -120px;} -.icon-random{background-position:-216px -120px;} -.icon-comment{background-position:-240px -120px;} -.icon-magnet{background-position:-264px -120px;} -.icon-chevron-up{background-position:-288px -120px;} -.icon-chevron-down{background-position:-313px -119px;} -.icon-retweet{background-position:-336px -120px;} -.icon-shopping-cart{background-position:-360px -120px;} -.icon-folder-close{background-position:-384px -120px;} -.icon-folder-open{background-position:-408px -120px;} -.icon-resize-vertical{background-position:-432px -119px;} -.icon-resize-horizontal{background-position:-456px -118px;} -.dropdown{position:relative;} -.dropdown-toggle{*margin-bottom:-3px;} -.dropdown-toggle:active,.open .dropdown-toggle{outline:0;} -.caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;opacity:0.3;filter:alpha(opacity=30);content:"\2193";} -.dropdown .caret{margin-top:8px;margin-left:2px;} -.dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100);} -.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;max-width:220px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;} -.dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;*width:100%;*margin:-5px 0 5px;} -.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;} -.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;} -.dropdown.open{*z-index:1000;}.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);} -.dropdown.open .dropdown-menu{display:block;} -.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);} -.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;} -.collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;} -.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;opacity:0.4;filter:alpha(opacity=40);cursor:pointer;} -.btn{display:inline-block;padding:4px 10px 4px;font-size:13px;line-height:18px;color:#333333;text-align:center;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#fafafa;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;*margin-left:.3em;}.btn:first-child{*margin-left:0;} -.btn:hover{color:#333333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-ms-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;} -.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} -.btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);background-color:#e6e6e6;background-color:#d9d9d9 \9;color:rgba(0, 0, 0, 0.5);outline:0;} -.btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} -.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} -.btn-large .icon{margin-top:1px;} -.btn-small{padding:5px 9px;font-size:11px;line-height:16px;} -.btn-small .icon{margin-top:-1px;} -.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;} -.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active{color:rgba(255, 255, 255, 0.75);} -.btn-primary{background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-ms-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(top, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#0044cc;} -.btn-primary:active,.btn-primary.active{background-color:#003399 \9;} -.btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-ms-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(top, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;} -.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;} -.btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-ms-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(top, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;} -.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;} -.btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-ms-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(top, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;} -.btn-success:active,.btn-success.active{background-color:#408140 \9;} -.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-ms-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(top, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;} -.btn-info:active,.btn-info.active{background-color:#24748c \9;} -button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;} -button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px;} -button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px;} -.btn-group{position:relative;*zoom:1;*margin-left:.3em;}.btn-group:before,.btn-group:after{display:table;content:"";} -.btn-group:after{clear:both;} -.btn-group:first-child{*margin-left:0;} -.btn-group+.btn-group{margin-left:5px;} -.btn-toolbar{margin-top:9px;margin-bottom:9px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;} -.btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} -.btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;} -.btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;} -.btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;} -.btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;} -.btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active,.btn-group .btn.active{z-index:2;} -.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;} -.btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;} -.btn-group.open{*z-index:1000;}.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} -.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);} -.btn .caret{margin-top:7px;margin-left:0;} -.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100);} -.btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret{border-top-color:#ffffff;opacity:0.75;filter:alpha(opacity=75);} -.btn-small .caret{margin-top:4px;} -.alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.alert,.alert-heading{color:#c09853;} -.alert .close{position:relative;top:-2px;right:-21px;line-height:18px;} -.alert-success{background-color:#dff0d8;border-color:#d6e9c6;} -.alert-success,.alert-success .alert-heading{color:#468847;} -.alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;} -.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48;} -.alert-info{background-color:#d9edf7;border-color:#bce8f1;} -.alert-info,.alert-info .alert-heading{color:#3a87ad;} -.alert-block{padding-top:14px;padding-bottom:14px;} -.alert-block>p,.alert-block>ul{margin-bottom:0;} -.alert-block p+p{margin-top:5px;} -.nav{margin-left:0;margin-bottom:18px;list-style:none;} -.nav>li>a{display:block;} -.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;} -.nav-list{padding-left:14px;padding-right:14px;margin-bottom:0;} -.nav-list>li>a,.nav-list .nav-header{display:block;padding:3px 15px;margin-left:-15px;margin-right:-15px;} -.nav-list .nav-header{font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-transform:uppercase;} -.nav-list>li+.nav-header{margin-top:9px;} -.nav-list .active>a,.nav-list .active>a:hover{color:#ffffff;background-color:#0088cc;} -.nav-list [class^="icon-"]{margin-right:2px;} -.nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";} -.nav-tabs:after,.nav-pills:after{clear:both;} -.nav-tabs>li,.nav-pills>li{float:left;} -.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;} -.nav-tabs{border-bottom:1px solid #ddd;} -.nav-tabs>li{margin-bottom:-1px;} -.nav-tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;} -.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;} -.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} -.nav-pills .active>a,.nav-pills .active>a:hover{color:#ffffff;background-color:#0088cc;} -.nav-stacked>li{float:none;} -.nav-stacked>li>a{margin-right:0;} -.nav-tabs.nav-stacked{border-bottom:0;} -.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} -.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;} -.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;} -.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;} -.nav-pills.nav-stacked>li>a{margin-bottom:3px;} -.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;} -.nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px;} -.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;} -.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;} -.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333333;} -.nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;} -.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;} -.nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;opacity:1;filter:alpha(opacity=100);} -.tabs-stacked .open>a:hover{border-color:#999999;} -.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";} -.tabbable:after{clear:both;} -.tabs-below .nav-tabs,.tabs-right .nav-tabs,.tabs-left .nav-tabs{border-bottom:0;} -.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;} -.tab-content>.active,.pill-content>.active{display:block;} -.tabs-below .nav-tabs{border-top:1px solid #ddd;} -.tabs-below .nav-tabs>li{margin-top:-1px;margin-bottom:0;} -.tabs-below .nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;} -.tabs-below .nav-tabs .active>a,.tabs-below .nav-tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;} -.tabs-left .nav-tabs>li,.tabs-right .nav-tabs>li{float:none;} -.tabs-left .nav-tabs>li>a,.tabs-right .nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;} -.tabs-left .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;} -.tabs-left .nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;} -.tabs-left .nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;} -.tabs-left .nav-tabs .active>a,.tabs-left .nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;} -.tabs-right .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;} -.tabs-right .nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;} -.tabs-right .nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;} -.tabs-right .nav-tabs .active>a,.tabs-right .nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;} -.navbar{overflow:visible;margin-bottom:18px;} -.btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#102a29;background-image:-moz-linear-gradient(top, #132e2b, #0c2327);background-image:-ms-linear-gradient(top, #132e2b, #0c2327);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#132e2b), to(#0c2327));background-image:-webkit-linear-gradient(top, #132e2b, #0c2327);background-image:-o-linear-gradient(top, #132e2b, #0c2327);background-image:linear-gradient(top, #132e2b, #0c2327);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#132e2b', endColorstr='#0c2327', GradientType=0);border-color:#0c2327 #0c2327 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);}.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#0c2327;} -.btn-navbar:active,.btn-navbar.active{background-color:#000000 \9;} -.btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);} -.btn-navbar .icon-bar+.icon-bar{margin-top:3px;} -.nav-collapse.collapse{height:auto;} -.navbar .brand:hover{text-decoration:none;} -.navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;} -.navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999999;}.navbar .navbar-text a:hover{color:#ffffff;background-color:transparent;} -.navbar .btn,.navbar .btn-group{margin-top:5px;} -.navbar .btn-group .btn{margin-top:0;} -.navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";} -.navbar-form:after{clear:both;} -.navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0;} -.navbar-form .radio,.navbar-form .checkbox{margin-top:5px;} -.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;} -.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Source Sans Pro", "Helvetica Neue", sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#666;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;} -.navbar-search .search-query::-webkit-input-placeholder{color:#eeeeee;} -.navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);} -.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;} -.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030;} -.navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;} -.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;} -.navbar .nav.pull-right{float:right;} -.navbar .nav>li{display:block;float:left;} -.navbar .nav>li>a{ - float:none; - padding: 15px; - height: 45px; - line-height: 45px; - color:#0B5567; - text-decoration:none; - font-size: 14px; - font-weight: 700; - border-left: 1px solid #ebebeb; - transition: all 200ms ease-in-out; -} -.navbar .nav>li:last-child a { - border-right: 1px solid #ebebeb; -} -.navbar .nav>li>a:hover { - background: #f5f5f5; - color:#0B5567; - text-decoration:none; - box-shadow: inset 0 4px 0 #15A9CE, inset 0 0 3px #ebebeb; - transition: all 200ms ease-in-out; -} -.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0c2327;background-color:rgba(0, 0, 0, 0.5);} -.navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#0c2327;border-right:1px solid #132e2b;} -.navbar .nav.pull-right{margin-left:10px;margin-right:0;} -.navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;} -.navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;} -.navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;} -.navbar .nav .active .caret{opacity:1;filter:alpha(opacity=100);} -.navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;} -.navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;} -.navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;} -.navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;} -.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:rgba(251, 251, 251, 0.7);background-image:-moz-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(245, 245, 245, 0.7));background-image:-ms-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(245, 245, 245, 0.7));background-image:-webkit-gradient(linear, 0 0, 0 100%, from(rgba(255, 255, 255, 0.7)), to(rgba(245, 245, 245, 0.7)));background-image:-webkit-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(245, 245, 245, 0.7));background-image:-o-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(245, 245, 245, 0.7));background-image:linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(245, 245, 245, 0.7));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255, 255, 255, 0.7)', endColorstr='rgba(245, 245, 245, 0.7)', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;} -.breadcrumb .divider{padding:0 5px;color:#999999;} -.breadcrumb .active a{color:#333333;} -.pagination{height:36px;margin:18px 0;} -.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);} -.pagination li{display:inline;} -.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;} -.pagination a:hover,.pagination .active a{background-color:#f5f5f5;} -.pagination .active a{color:#999999;cursor:default;} -.pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;} -.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;} -.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;} -.pagination-centered{text-align:center;} -.pagination-right{text-align:right;} -.pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";} -.pager:after{clear:both;} -.pager li{display:inline;} -.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;} -.pager a:hover{text-decoration:none;background-color:#f5f5f5;} -.pager .next a{float:right;} -.pager .previous a{float:left;} -.modal-open .dropdown-menu{z-index:2050;} -.modal-open .dropdown.open{*z-index:2050;} -.modal-open .popover{z-index:2060;} -.modal-open .tooltip{z-index:2070;} -.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;} -.modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);} -.modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;} -.modal.fade.in{top:50%;} -.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;} -.modal-body{padding:15px;} -.modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";} -.modal-footer:after{clear:both;} -.modal-footer .btn{float:right;margin-left:5px;margin-bottom:0;} -.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} -.tooltip.top{margin-top:-2px;} -.tooltip.right{margin-left:2px;} -.tooltip.bottom{margin-top:2px;} -.tooltip.left{margin-left:-2px;} -.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} -.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} -.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} -.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} -.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.tooltip-arrow{position:absolute;width:0;height:0;} -.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;} -.popover.right{margin-left:5px;} -.popover.bottom{margin-top:5px;} -.popover.left{margin-left:-5px;} -.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} -.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} -.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} -.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} -.popover .arrow{position:absolute;width:0;height:0;} -.popover-inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);} -.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;} -.popover-content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;} -.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";} -.thumbnails:after{clear:both;} -.thumbnails>li{float:left;margin:0 0 18px 20px;} -.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);} -a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);} -.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;} -.thumbnail .caption{padding:9px;} -.label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} -.label-important{background-color:#b94a48;} -.label-warning{background-color:#f89406;} -.label-success{background-color:#468847;} -.label-info{background-color:#3a87ad;} -@-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.progress .bar{width:0%;height:18px;color:#ffffff;font-size:12px;text-align:center;background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;} -.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;} -.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;} -.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);} -.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} -.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);} -.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} -.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);} -.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);} -.accordion{margin-bottom:18px;} -.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.accordion-heading{border-bottom:0;} -.accordion-heading .accordion-toggle{display:block;padding:8px 15px;} -.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;} -.carousel{position:relative;margin-bottom:18px;line-height:1;} -.carousel-inner{overflow:hidden;width:100%;position:relative;} -.carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;} -.carousel .item>img{display:block;line-height:1;} -.carousel .active,.carousel .next,.carousel .prev{display:block;} -.carousel .active{left:0;} -.carousel .next,.carousel .prev{position:absolute;top:0;width:100%;} -.carousel .next{left:100%;} -.carousel .prev{left:-100%;} -.carousel .next.left,.carousel .prev.right{left:0;} -.carousel .active.left{left:-100%;} -.carousel .active.right{left:100%;} -.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;} -.carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);} -.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);} -.carousel-caption h4,.carousel-caption p{color:#ffffff;} -.hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;} -.hero-unit p{font-size:18px;font-weight:200;line-height:27px;} -.pull-right{float:right;} -.pull-left{float:left;} -.hide{display:none;} -.show{display:block;} -.invisible{visibility:hidden;} diff --git a/akka-docs-dev/_sphinx/themes/akka/static/toc.js b/akka-docs-dev/_sphinx/themes/akka/static/toc.js deleted file mode 100644 index 98f18fd518..0000000000 --- a/akka-docs-dev/_sphinx/themes/akka/static/toc.js +++ /dev/null @@ -1,131 +0,0 @@ -/*! - * samaxesJS JavaScript Library - * jQuery TOC Plugin v1.1.3 - * http://code.google.com/p/samaxesjs/ - * - * Copyright (c) 2011 samaxes.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function($) { - - /* - * The TOC plugin dynamically builds a table of contents from the headings in - * a document and prepends legal-style section numbers to each of the headings. - */ - $.fn.toc = function(options) { - var opts = $.extend({}, $.fn.toc.defaults, options); - var toc = this.append('
    ').children('ul'); - var headers = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0}; - var index = 0; - var indexes = {h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0}; - for (var i = 1; i <= 6; i++) { - indexes['h' + i] = (opts.exclude.match(new RegExp('h' + i, 'i')) === null && $('h' + i).length > 0) ? ++index : 0; - } - - return this.each(function() { - $(opts.context + ' :header').not(opts.exclude).each(function() { - var $this = $(this); - for (var i = 6; i >= 1; i--) { - if ($this.is('h' + i)) { - if (opts.numerate) { - checkContainer(headers['h' + i], toc); - updateNumeration(headers, 'h' + i); - if (opts.autoId && !$this.attr('id')) { - $this.attr('id', generateId($this.text())); - } - $this.text(addNumeration(headers, 'h' + i, $this.text())); - } - if (opts.autoId && !$this.attr('id')) { - $this.attr('id', generateId($this.text())); - } - appendToTOC(toc, indexes['h' + i], $this.attr('id'), $this.text()); - } - } - }); - }); - }; - - /* - * Checks if the last node is an 'ul' element. - * If not, a new one is created. - */ - function checkContainer(header, toc) { - if (header === 0 && toc.find(':last').length !== 0 && !toc.find(':last').is('ul')) { - toc.find('li:last').append('
      '); - } - }; - - /* - * Updates headers numeration. - */ - function updateNumeration(headers, header) { - $.each(headers, function(i, val) { - if (i === header) { - ++headers[i]; - } else if (i > header) { - headers[i] = 0; - } - }); - }; - - /* - * Generate an anchor id from a string by replacing unwanted characters. - */ - function generateId(text) { - return text.replace(/[ <#\/\\?&.,():;]/g, '_'); - }; - - /* - * Prepends the numeration to a heading. - */ - function addNumeration(headers, header, text) { - var numeration = ''; - - $.each(headers, function(i, val) { - if (i <= header && headers[i] > 0) { - numeration += headers[i] + '.'; - } - }); - - return numeration + ' ' + text; - }; - - /* - * Appends a new node to the TOC. - */ - function appendToTOC(toc, index, id, text) { - var parent = toc; - - for (var i = 1; i < index; i++) { - if (parent.find('> li:last > ul').length === 0) { - parent.append('
      • '); - } - parent = parent.find('> li:last > ul:first'); - } - - if (id === '') { - parent.append('
      • ' + text + '
      • '); - } else { - parent.append('
      • ' + text + '
      • '); - } - }; - - $.fn.toc.defaults = { - exclude: 'h1, h5, h6', - context: '', - autoId: true, - numerate: false - }; -})(jQuery); diff --git a/akka-docs-dev/_sphinx/themes/akka/static/watermark.png b/akka-docs-dev/_sphinx/themes/akka/static/watermark.png deleted file mode 100644 index dfbc5d5e2cc97d7bea0b002b0b0294c0d7c50f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2442 zcmeAS@N?(olHy`uVBq!ia0y~yVCZ0AU`XL$V_;y^vi7iLU|^6eag8Vm&QB{TPb^Ah za7@WhN>%X8O-xS>N=;0uEIgTN!@$6)dqanLXIm@BZRw8|iv;D=QluL0 zT6;WT7btJaSdeW!A?CJ&fuW-#<3!F4jO!OJVQOHIl9}1RVo$T~w+Wwl19#3?@x*@} zBTKPi!28OePyEWNGx?uMi7D~^U^pVoxvS;QALbGtW^OrVsgqj%8zeR`WnAW6;mYT5 zs!_xFg0Rq}AB+m64GDQ_;tVVo7C827Iq{~Yh|}zVi|Xn3kF|37cYHZ(!!(ME4x9kLto+J-^LpZvy&wXBlgLMpKNB1X^8UD(qP}!DtuT` z<<~ypTXhTFOiVXSc-Y~_CdDA8bhWW2kF(?_t5LBR>x4%NyJQ%%1Q>$eck1$5J7GRMl~ zMF#{wPdq(`F;go@Nc2jM#NXwv+tOt?+!MG()w0yRW<8a9G2wW1R#ey7U>z2d1{np1 zWwrbZ)^6hu*vBMreDWN(6Fpo>(YXrep9)`2Q@twKo1%7$Z52Th1c;$12oSLRrz0VtS4l=I|V{kjqEXF1Dgj0Y`>J#JH1kQ}d5sfEI zJ~3EkIZV6qxR|AgOFiKOx58G2wdoE8GBX|o$ZXvua$&+Lg&Elk#FW@SGiH6uc2I1U zTXm$(D3;NIp?8tuy>jgz{hUH>Q3`wh`^#iVoNHA0FyH2a!5yZgfAyyv4;OH7WHq-f zl;Gg|pUExM=H)QwzrVdh(E@`@t0yceW1q(|fg^`eZ^5k$mR81#{JGuxn zkjLVN1t}(}4#8Z)qRfny??Mv<#Nu6+inwX9uw=}geo$c5gAdC@+_;z?*~{88M*Z0| zxyey8V7|Ob2j}d|B`xb37wR}H@XWL8we^2zW2L!3ro(n4E7wNv8yS%vk7AFyCKoW+ z27KVH)Mi-u+vE(BHoND{O^lV9jNIGQOefs3KNG}cCvc!)%Qm*!LZyr^o9CYrJIC@! zym^oH!UnrDJj_>kdfeI+IU-i%$mJ|F<7o&w##uD|zraO%CSQ|`fGjbc(gfX*lR5D* z3{qJZ9+T`3nuh$~3U%YUE!}lup*6?pHYTRCtrK_e3n~Icc%iOA}l~Hyf;5 z%X+9`d$HQ5^2vKugxQpT?w_-Y`LdIPgwFK&H99LzH_b3hm8f2{>i^>>NgSnr&CRC0 zn3yo(dVMmhv7~Xw)J3bmE~w~CYY8kk)bUkFkM*M8TyCc~Vy{$ZF&_IKVUV;(MR}j3 zprvES^b93|>yw0*1e&J#NC_F~Up!$Dr*eqnqtKbO;?7ft6Z8+}REhH*zV02A{-I}O zfZE4NBBDx9#C8kLcNJ2uAezP8e#hb^f&{UFCdSxu3wxyl`r z8V{_|d3uv~cE$p4TZR8;tE=BY$Gn$ZOrPZ>ro{4PEWRm}`}SR&W$}kKZ-gdJ*&AotS}v)~ zv$88~!jx%i(wf?#Y)NuQD%{n{%zKqeV7v^|PEX?fpUBy3~QEq<|x;lK{b3zCrvog6(gTlqHRC`?q@T0g1NTi3WdzdM*=`L^YHv%H>sEN?3G z-ptQ^x_}|n*894j65pjsB~DwnP4EtVc*XOGHM%Crx*R z@t;!&oaofZXUM!iYTbWc^VAhT75I|M-YoL7s+HO4li5AVqT|^TVecz83vM40)m_eX z;)lT@%k>|aCaE|W?0erbaYFkVW9f%(tW2(Mi7Lk=0~h;Es^D{*TcW4jdU(fV6*;Gg z?|Nd-IHZUOJr$H#s6JQcuiqpM{)P4QVimzTpFfo@WEQ%-_Ea&Kvf`BGFF5=kEE9bwadm@FU!#j8lXATxL8rg@0qeb;?~Wh6k$UdnnPf$ggIX2(nh1_lOCS3j3^ HP6 outlet = null; - - Outlet outlet1 = null; - Outlet outlet2 = null; - - Inlet inlet = null; - - Inlet inlet1 = null; - Inlet inlet2 = null; - - Flow flow = Flow.of(Integer.class); - Flow flow1 = Flow.of(Integer.class); - Flow flow2 = Flow.of(Integer.class); - - Promise> promise = null; - - - { - Graph, BoxedUnit> graphSource = null; - Graph, BoxedUnit> graphSink = null; - Graph, BoxedUnit> graphFlow = null; - - //#flow-wrap - Source source = Source.fromGraph(graphSource); - Sink sink = Sink.fromGraph(graphSink); - Flow aflow = Flow.fromGraph(graphFlow); - Flow.fromSinkAndSource(Sink.head(), Source.single(0)); - Flow.fromSinkAndSourceMat(Sink.head(), Source.single(0), Keep.left()); - //#flow-wrap - - Graph, BoxedUnit> bidiGraph = null; - - //#bidi-wrap - BidiFlow bidiFlow = - BidiFlow.fromGraph(bidiGraph); - BidiFlow.fromFlows(flow1, flow2); - BidiFlow.fromFlowsMat(flow1, flow2, Keep.both()); - //#bidi-wrap - - } - - { - //#graph-create - GraphDSL.create(builder -> { - //... - return ClosedShape.getInstance(); - }); - - GraphDSL.create(builder -> { - //... - return new FlowShape<>(inlet, outlet); - }); - //#graph-create - } - - { - //#graph-create-2 - GraphDSL.create(builder -> { - //... - return SourceShape.of(outlet); - }); - - GraphDSL.create(builder -> { - //... - return SinkShape.of(inlet); - }); - - GraphDSL.create(builder -> { - //... - return FlowShape.of(inlet, outlet); - }); - - GraphDSL.create(builder -> { - //... - return BidiShape.of(inlet1, outlet1, inlet2, outlet2); - }); - //#graph-create-2 - } - - { - //#graph-builder - GraphDSL.create(builder -> { - builder.from(outlet).toInlet(inlet); - builder.from(outlet).via(builder.add(flow)).toInlet(inlet); - builder.from(builder.add(Source.single(0))).to(builder.add(Sink.head())); - //... - return ClosedShape.getInstance(); - }); - //#graph-builder - } - - //#source-creators - Source>> src = Source.maybe(); - // Complete the promise with an empty option to emulate the old lazyEmpty - promise.trySuccess(scala.Option.empty()); - - final Source ticks = Source.tick( - FiniteDuration.create(0, TimeUnit.MILLISECONDS), - FiniteDuration.create(200, TimeUnit.MILLISECONDS), - "tick"); - - final Source pubSource = - Source.fromPublisher(TestPublisher.manualProbe(true, sys)); - - final Source futSource = - Source.fromFuture(Futures.successful(42)); - - final Source> subSource = - Source.asSubscriber(); - //#source-creators - - //#sink-creators - final Sink subSink = - Sink.fromSubscriber(TestSubscriber.manualProbe(sys)); - //#sink-creators - - //#sink-as-publisher - final Sink> pubSink = - Sink.asPublisher(false); - - final Sink> pubSinkFanout = - Sink.asPublisher(true); - //#sink-as-publisher - - //#empty-flow - Flow emptyFlow = Flow.create(); - // or - Flow emptyFlow2 = Flow.of(Integer.class); - //#empty-flow - - //#flatMapConcat - Flow.>create(). - flatMapConcat(new Function, Source>(){ - @Override public Source apply(Source param) throws Exception { - return param; - } - }); - //#flatMapConcat - - Uri uri = null; - //#raw-query - final akka.japi.Option theRawQueryString = uri.rawQueryString(); - //#raw-query - - //#query-param - final akka.japi.Option aQueryParam = uri.query().get("a"); - //#query-param - - //#file-source-sink - final Source> fileSrc = - FileIO.fromFile(new File(".")); - - final Source> otherFileSrc = - FileIO.fromFile(new File("."), 1024); - - final Sink> fileSink = - FileIO.toFile(new File(".")); - //#file-source-sink - - //#input-output-stream-source-sink - final Source> inputStreamSrc = - StreamConverters.fromInputStream(new Creator(){ - public InputStream create() { - return new SomeInputStream(); - } - }); - - final Source> otherInputStreamSrc = - StreamConverters.fromInputStream(new Creator(){ - public InputStream create() { - return new SomeInputStream(); - } - }, 1024); - - final Sink> outputStreamSink = - StreamConverters.fromOutputStream(new Creator(){ - public OutputStream create() { - return new SomeOutputStream(); - } - }); - //#input-output-stream-source-sink - - - //#output-input-stream-source-sink - final FiniteDuration timeout = FiniteDuration.Zero(); - - final Source outputStreamSrc = - StreamConverters.asOutputStream(); - - final Source otherOutputStreamSrc = - StreamConverters.asOutputStream(timeout); - - final Sink someInputStreamSink = - StreamConverters.asInputStream(); - - final Sink someOtherInputStreamSink = - StreamConverters.asInputStream(timeout); - //#output-input-stream-source-sink - - } - -} diff --git a/akka-docs-dev/rst/scala.rst b/akka-docs-dev/rst/scala.rst deleted file mode 100644 index 78cc44e68e..0000000000 --- a/akka-docs-dev/rst/scala.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _stream-scala-api: - -Scala Documentation -=================== - -.. toctree:: - :maxdepth: 3 - - scala/stream-index - scala/http/index diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala.orig b/akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala.orig deleted file mode 100644 index cab7a27ca1..0000000000 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala.orig +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (C) 2009-2014 Typesafe Inc. - */ - -package docs.http.scaladsl -<<<<<<< 53710dc764ea110a746112f2bd6010494fa1f9ac - -import akka.actor.{ ActorRef, ActorSystem } -import akka.event.LoggingAdapter -import akka.http.scaladsl.Http -import akka.http.scaladsl.Http.ServerBinding -import akka.http.scaladsl.model._ -import akka.stream.ActorMaterializer -import akka.stream.scaladsl.{ Flow, Sink } -import akka.stream.stage.{ Context, PushStage } -import akka.testkit.TestActors -import org.scalatest.{ Matchers, WordSpec } -import scala.language.postfixOps - -import scala.concurrent.{ ExecutionContext, Future } -======= -/* -// FIXME, uncomment this! - -import scala.concurrent.Future -import org.scalatest.{ WordSpec, Matchers } -import akka.actor.ActorSystem ->>>>>>> =htc,doc #18535 improved docs on spray-json usage - -class HttpServerExampleSpec extends WordSpec with Matchers { - - // never actually called - val log: LoggingAdapter = null - - def compileOnlySpec(body: => Unit) = () - - "binding-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.stream.ActorMaterializer - import akka.stream.scaladsl._ - - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - val serverSource: Source[Http.IncomingConnection, Future[Http.ServerBinding]] = - Http().bind(interface = "localhost", port = 8080) - val bindingFuture: Future[Http.ServerBinding] = - serverSource.to(Sink.foreach { connection => // foreach materializes the source - println("Accepted new connection from " + connection.remoteAddress) - // ... and then actually handle the connection - }).run() - } - - "binding-failure-high-level-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.http.scaladsl.server.Directives._ - import akka.stream.ActorMaterializer - - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - val handler = get { - complete("Hello world!") - } - - // let's say the OS won't allow us to bind to 80. - val (host, port) = ("localhost", 80) - val bindingFuture: Future[ServerBinding] = - Http().bindAndHandle(handler, host, port) - - bindingFuture onFailure { - case ex: Exception => - log.error(ex, "Failed to bind to {}:{}!", host, port) - } - - } - - // mock values: - val handleConnections: Sink[Http.IncomingConnection, Future[Http.ServerBinding]] = - Sink.ignore.mapMaterializedValue(_ => Future.failed(new Exception(""))) - - "binding-failure-handling" in compileOnlySpec { - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - // let's say the OS won't allow us to bind to 80. - val (host, port) = ("localhost", 80) - val serverSource = Http().bind(host, port) - - val bindingFuture: Future[ServerBinding] = serverSource - .to(handleConnections) // Sink[Http.IncomingConnection, _] - .run() - - bindingFuture onFailure { - case ex: Exception => - log.error(ex, "Failed to bind to {}:{}!", host, port) - } - } - - object MyExampleMonitoringActor { - def props = TestActors.echoActorProps - } - - "incoming-connections-source-failure-handling" in compileOnlySpec { - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - import Http._ - val (host, port) = ("localhost", 8080) - val serverSource = Http().bind(host, port) - - val failureMonitor: ActorRef = system.actorOf(MyExampleMonitoringActor.props) - - val reactToTopLevelFailures = Flow[IncomingConnection] - .transform { () => - new PushStage[IncomingConnection, IncomingConnection] { - override def onPush(elem: IncomingConnection, ctx: Context[IncomingConnection]) = - ctx.push(elem) - - override def onUpstreamFailure(cause: Throwable, ctx: Context[IncomingConnection]) = { - failureMonitor ! cause - super.onUpstreamFailure(cause, ctx) - } - } - } - - serverSource - .via(reactToTopLevelFailures) - .to(handleConnections) // Sink[Http.IncomingConnection, _] - .run() - } - - "connection-stream-failure-handling" in compileOnlySpec { - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - val (host, port) = ("localhost", 8080) - val serverSource = Http().bind(host, port) - - val reactToConnectionFailure = Flow[HttpRequest] - .transform { () => - new PushStage[HttpRequest, HttpRequest] { - override def onPush(elem: HttpRequest, ctx: Context[HttpRequest]) = - ctx.push(elem) - - override def onUpstreamFailure(cause: Throwable, ctx: Context[HttpRequest]) = { - // handle the failure somehow - super.onUpstreamFailure(cause, ctx) - } - } - } - - val httpEcho = Flow[HttpRequest] - .via(reactToConnectionFailure) - .map { request => - // simple text "echo" response: - HttpResponse(entity = HttpEntity(ContentTypes.`text/plain`, request.entity.dataBytes)) - } - - serverSource - .runForeach { con => - con.handleWith(httpEcho) - } - } - - "full-server-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.http.scaladsl.model.HttpMethods._ - import akka.http.scaladsl.model._ - import akka.stream.ActorMaterializer - import akka.stream.scaladsl.Sink - - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - - val serverSource = Http().bind(interface = "localhost", port = 8080) - - val requestHandler: HttpRequest => HttpResponse = { - case HttpRequest(GET, Uri.Path("/"), _, _, _) => - HttpResponse(entity = HttpEntity(MediaTypes.`text/html`, - "Hello world!")) - - case HttpRequest(GET, Uri.Path("/ping"), _, _, _) => - HttpResponse(entity = "PONG!") - - case HttpRequest(GET, Uri.Path("/crash"), _, _, _) => - sys.error("BOOM!") - - case _: HttpRequest => - HttpResponse(404, entity = "Unknown resource!") - } - - val bindingFuture: Future[Http.ServerBinding] = - serverSource.to(Sink.foreach { connection => - println("Accepted new connection from " + connection.remoteAddress) - - connection handleWithSyncHandler requestHandler - // this is equivalent to - // connection handleWith { Flow[HttpRequest] map requestHandler } - }).run() - } - - "low-level-server-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.http.scaladsl.model.HttpMethods._ - import akka.http.scaladsl.model._ - import akka.stream.ActorMaterializer - - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - - val requestHandler: HttpRequest => HttpResponse = { - case HttpRequest(GET, Uri.Path("/"), _, _, _) => - HttpResponse(entity = HttpEntity(MediaTypes.`text/html`, - "Hello world!")) - - case HttpRequest(GET, Uri.Path("/ping"), _, _, _) => - HttpResponse(entity = "PONG!") - - case HttpRequest(GET, Uri.Path("/crash"), _, _, _) => - sys.error("BOOM!") - - case _: HttpRequest => - HttpResponse(404, entity = "Unknown resource!") - } - - Http().bindAndHandleSync(requestHandler, "localhost", 8080) - } - - // format: OFF - - "high-level-server-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ - import akka.http.scaladsl.server.Directives._ - import akka.stream.ActorMaterializer - - implicit val system = ActorSystem() - implicit val materializer = ActorMaterializer() - - val route = - get { - pathSingleSlash { - complete { - - Hello world! - - } - } ~ - path("ping") { - complete("PONG!") - } ~ - path("crash") { - sys.error("BOOM!") - } - } - - // `route` will be implicitly converted to `Flow` using `RouteResult.route2HandlerFlow` - Http().bindAndHandle(route, "localhost", 8080) - } - - "minimal-routing-example" in compileOnlySpec { - import akka.http.scaladsl.Http - import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ - import akka.http.scaladsl.server.Directives._ - import akka.stream.ActorMaterializer - - object Main extends App { - implicit val system = ActorSystem("my-system") - implicit val materializer = ActorMaterializer() - implicit val ec = system.dispatcher - - val route = - path("hello") { - get { - complete { -

        Say hello to akka-http

        - } - } - } - - val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) - - println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") - Console.readLine() // for the future transformations - bindingFuture - .flatMap(_.unbind()) // trigger unbinding from the port - .onComplete(_ ⇒ system.shutdown()) // and shutdown when done - } - } - - "long-routing-example" in compileOnlySpec { - //#long-routing-example - import akka.actor.ActorRef - import akka.http.scaladsl.coding.Deflate - import akka.http.scaladsl.marshalling.ToResponseMarshaller - import akka.http.scaladsl.model.StatusCodes.MovedPermanently - import akka.http.scaladsl.server.Directives._ - // TODO: these explicit imports are only needed in complex cases, like below; Also, not needed on Scala 2.11 - import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet - import akka.http.scaladsl.server.directives.FormFieldDirectives.FieldMagnet - import akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller - import akka.pattern.ask - import akka.util.Timeout - - // types used by the API routes - type Money = Double // only for demo purposes, don't try this at home! - type TransactionResult = String - case class User(name: String) - case class Order(email: String, amount: Money) - case class Update(order: Order) - case class OrderItem(i: Int, os: Option[String], s: String) - - // marshalling would usually be derived automatically using libraries - implicit val orderUM: FromRequestUnmarshaller[Order] = ??? - implicit val orderM: ToResponseMarshaller[Order] = ??? - implicit val orderSeqM: ToResponseMarshaller[Seq[Order]] = ??? - implicit val timeout: Timeout = ??? // for actor asks - implicit val ec: ExecutionContext = ??? - implicit val mat: ActorMaterializer = ??? - implicit val sys: ActorSystem = ??? - - // backend entry points - def myAuthenticator: Authenticator[User] = ??? - def retrieveOrdersFromDB: Seq[Order] = ??? - def myDbActor: ActorRef = ??? - def processOrderRequest(id: Int, complete: Order => Unit): Unit = ??? - - val route = { - path("orders") { - authenticateBasic(realm = "admin area", myAuthenticator) { user => - get { - encodeResponseWith(Deflate) { - complete { - // marshal custom object with in-scope marshaller - retrieveOrdersFromDB - } - } - } ~ - post { - // decompress gzipped or deflated requests if required - decodeRequest { - // unmarshal with in-scope unmarshaller - entity(as[Order]) { order => - complete { - // ... write order to DB - "Order received" - } - } - } - } - } - } ~ - // extract URI path element as Int - pathPrefix("order" / IntNumber) { orderId => - pathEnd { - (put | parameter('method ! "put")) { - // form extraction from multipart or www-url-encoded forms - formFields('email, 'total.as[Money]).as(Order) { order => - complete { - // complete with serialized Future result - (myDbActor ? Update(order)).mapTo[TransactionResult] - } - } - } ~ - get { - // debugging helper - logRequest("GET-ORDER") { - // use in-scope marshaller to create completer function - completeWith(instanceOf[Order]) { completer => - // custom - processOrderRequest(orderId, completer) - } - } - } - } ~ - path("items") { - get { - // parameters to case class extraction - parameters('size.as[Int], 'color ?, 'dangerous ? "no") - .as(OrderItem) { orderItem => - // ... route using case class instance created from - // required and optional query parameters - complete("") // hide - } - } - } - } ~ - pathPrefix("documentation") { - // optionally compresses the response with Gzip or Deflate - // if the client accepts compressed responses - encodeResponse { - // serve up static content from a JAR resource - getFromResourceDirectory("docs") - } - } ~ - path("oldApi" / Rest) { pathRest => - redirect("http://oldapi.example.com/" + pathRest, MovedPermanently) - } - } - } -} diff --git a/akka-docs-dev/rst/stream-configuration.rst b/akka-docs-dev/rst/stream-configuration.rst deleted file mode 100644 index 520a4c6387..0000000000 --- a/akka-docs-dev/rst/stream-configuration.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _stream-config: - -############# -Configuration -############# - -.. literalinclude:: ../../akka-stream/src/main/resources/reference.conf \ No newline at end of file diff --git a/akka-docs-dev/src/test/resources/application.conf b/akka-docs-dev/src/test/resources/application.conf deleted file mode 100644 index dafc521805..0000000000 --- a/akka-docs-dev/src/test/resources/application.conf +++ /dev/null @@ -1 +0,0 @@ -akka.loggers = ["akka.testkit.TestEventListener"] \ No newline at end of file diff --git a/akka-docs-dev/_sphinx/exts/includecode2.py b/akka-docs/_sphinx/exts/includecode2.py similarity index 100% rename from akka-docs-dev/_sphinx/exts/includecode2.py rename to akka-docs/_sphinx/exts/includecode2.py diff --git a/akka-docs/rst/conf.py b/akka-docs/rst/conf.py index ec706cd072..b38afeb563 100644 --- a/akka-docs/rst/conf.py +++ b/akka-docs/rst/conf.py @@ -8,7 +8,7 @@ import sys, os # -- General configuration ----------------------------------------------------- sys.path.append(os.path.abspath('../_sphinx/exts')) -extensions = ['sphinx.ext.todo', 'includecode'] +extensions = ['sphinx.ext.todo', 'includecode', 'includecode2'] templates_path = ['_templates'] source_suffix = '.rst' diff --git a/akka-docs-dev/rst/stages-overview.rst b/akka-docs/rst/general/stream/stages-overview.rst similarity index 100% rename from akka-docs-dev/rst/stages-overview.rst rename to akka-docs/rst/general/stream/stages-overview.rst diff --git a/akka-docs/rst/general/stream/stream-configuration.rst b/akka-docs/rst/general/stream/stream-configuration.rst new file mode 100644 index 0000000000..5257351bf5 --- /dev/null +++ b/akka-docs/rst/general/stream/stream-configuration.rst @@ -0,0 +1,7 @@ +.. _stream-config: + +############# +Configuration +############# + +.. literalinclude:: ../../../../akka-stream/src/main/resources/reference.conf \ No newline at end of file diff --git a/akka-docs-dev/rst/stream-design.rst b/akka-docs/rst/general/stream/stream-design.rst similarity index 100% rename from akka-docs-dev/rst/stream-design.rst rename to akka-docs/rst/general/stream/stream-design.rst diff --git a/akka-docs-dev/rst/images/akka-http-file-listing.png b/akka-docs/rst/images/akka-http-file-listing.png similarity index 100% rename from akka-docs-dev/rst/images/akka-http-file-listing.png rename to akka-docs/rst/images/akka-http-file-listing.png diff --git a/akka-docs-dev/rst/images/asyncBoundary.png b/akka-docs/rst/images/asyncBoundary.png similarity index 100% rename from akka-docs-dev/rst/images/asyncBoundary.png rename to akka-docs/rst/images/asyncBoundary.png diff --git a/akka-docs-dev/rst/images/compose_attributes.png b/akka-docs/rst/images/compose_attributes.png similarity index 100% rename from akka-docs-dev/rst/images/compose_attributes.png rename to akka-docs/rst/images/compose_attributes.png diff --git a/akka-docs-dev/rst/images/compose_composites.png b/akka-docs/rst/images/compose_composites.png similarity index 100% rename from akka-docs-dev/rst/images/compose_composites.png rename to akka-docs/rst/images/compose_composites.png diff --git a/akka-docs-dev/rst/images/compose_graph.png b/akka-docs/rst/images/compose_graph.png similarity index 100% rename from akka-docs-dev/rst/images/compose_graph.png rename to akka-docs/rst/images/compose_graph.png diff --git a/akka-docs-dev/rst/images/compose_graph_flow.png b/akka-docs/rst/images/compose_graph_flow.png similarity index 100% rename from akka-docs-dev/rst/images/compose_graph_flow.png rename to akka-docs/rst/images/compose_graph_flow.png diff --git a/akka-docs-dev/rst/images/compose_graph_partial.png b/akka-docs/rst/images/compose_graph_partial.png similarity index 100% rename from akka-docs-dev/rst/images/compose_graph_partial.png rename to akka-docs/rst/images/compose_graph_partial.png diff --git a/akka-docs-dev/rst/images/compose_graph_shape.png b/akka-docs/rst/images/compose_graph_shape.png similarity index 100% rename from akka-docs-dev/rst/images/compose_graph_shape.png rename to akka-docs/rst/images/compose_graph_shape.png diff --git a/akka-docs-dev/rst/images/compose_mat.png b/akka-docs/rst/images/compose_mat.png similarity index 100% rename from akka-docs-dev/rst/images/compose_mat.png rename to akka-docs/rst/images/compose_mat.png diff --git a/akka-docs-dev/rst/images/compose_nested_flow.png b/akka-docs/rst/images/compose_nested_flow.png similarity index 100% rename from akka-docs-dev/rst/images/compose_nested_flow.png rename to akka-docs/rst/images/compose_nested_flow.png diff --git a/akka-docs-dev/rst/images/compose_nested_flow_opaque.png b/akka-docs/rst/images/compose_nested_flow_opaque.png similarity index 100% rename from akka-docs-dev/rst/images/compose_nested_flow_opaque.png rename to akka-docs/rst/images/compose_nested_flow_opaque.png diff --git a/akka-docs-dev/rst/images/compose_shapes.png b/akka-docs/rst/images/compose_shapes.png similarity index 100% rename from akka-docs-dev/rst/images/compose_shapes.png rename to akka-docs/rst/images/compose_shapes.png diff --git a/akka-docs-dev/rst/images/composition.png b/akka-docs/rst/images/composition.png similarity index 100% rename from akka-docs-dev/rst/images/composition.png rename to akka-docs/rst/images/composition.png diff --git a/akka-docs-dev/rst/images/composition.svg b/akka-docs/rst/images/composition.svg similarity index 100% rename from akka-docs-dev/rst/images/composition.svg rename to akka-docs/rst/images/composition.svg diff --git a/akka-docs-dev/rst/images/graph_stage_chain.png b/akka-docs/rst/images/graph_stage_chain.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_chain.png rename to akka-docs/rst/images/graph_stage_chain.png diff --git a/akka-docs-dev/rst/images/graph_stage_chain.svg b/akka-docs/rst/images/graph_stage_chain.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_chain.svg rename to akka-docs/rst/images/graph_stage_chain.svg diff --git a/akka-docs-dev/rst/images/graph_stage_conceptual.png b/akka-docs/rst/images/graph_stage_conceptual.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_conceptual.png rename to akka-docs/rst/images/graph_stage_conceptual.png diff --git a/akka-docs-dev/rst/images/graph_stage_conceptual.svg b/akka-docs/rst/images/graph_stage_conceptual.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_conceptual.svg rename to akka-docs/rst/images/graph_stage_conceptual.svg diff --git a/akka-docs-dev/rst/images/graph_stage_detached_tracks_1.png b/akka-docs/rst/images/graph_stage_detached_tracks_1.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_detached_tracks_1.png rename to akka-docs/rst/images/graph_stage_detached_tracks_1.png diff --git a/akka-docs-dev/rst/images/graph_stage_detached_tracks_1.svg b/akka-docs/rst/images/graph_stage_detached_tracks_1.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_detached_tracks_1.svg rename to akka-docs/rst/images/graph_stage_detached_tracks_1.svg diff --git a/akka-docs-dev/rst/images/graph_stage_detached_tracks_2.png b/akka-docs/rst/images/graph_stage_detached_tracks_2.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_detached_tracks_2.png rename to akka-docs/rst/images/graph_stage_detached_tracks_2.png diff --git a/akka-docs-dev/rst/images/graph_stage_detached_tracks_2.svg b/akka-docs/rst/images/graph_stage_detached_tracks_2.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_detached_tracks_2.svg rename to akka-docs/rst/images/graph_stage_detached_tracks_2.svg diff --git a/akka-docs-dev/rst/images/graph_stage_duplicate.png b/akka-docs/rst/images/graph_stage_duplicate.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_duplicate.png rename to akka-docs/rst/images/graph_stage_duplicate.png diff --git a/akka-docs-dev/rst/images/graph_stage_duplicate.svg b/akka-docs/rst/images/graph_stage_duplicate.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_duplicate.svg rename to akka-docs/rst/images/graph_stage_duplicate.svg diff --git a/akka-docs-dev/rst/images/graph_stage_filter.png b/akka-docs/rst/images/graph_stage_filter.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_filter.png rename to akka-docs/rst/images/graph_stage_filter.png diff --git a/akka-docs-dev/rst/images/graph_stage_filter.svg b/akka-docs/rst/images/graph_stage_filter.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_filter.svg rename to akka-docs/rst/images/graph_stage_filter.svg diff --git a/akka-docs-dev/rst/images/graph_stage_map.png b/akka-docs/rst/images/graph_stage_map.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_map.png rename to akka-docs/rst/images/graph_stage_map.png diff --git a/akka-docs-dev/rst/images/graph_stage_map.svg b/akka-docs/rst/images/graph_stage_map.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_map.svg rename to akka-docs/rst/images/graph_stage_map.svg diff --git a/akka-docs-dev/rst/images/graph_stage_tracks_1.png b/akka-docs/rst/images/graph_stage_tracks_1.png similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_tracks_1.png rename to akka-docs/rst/images/graph_stage_tracks_1.png diff --git a/akka-docs-dev/rst/images/graph_stage_tracks_1.svg b/akka-docs/rst/images/graph_stage_tracks_1.svg similarity index 100% rename from akka-docs-dev/rst/images/graph_stage_tracks_1.svg rename to akka-docs/rst/images/graph_stage_tracks_1.svg diff --git a/akka-docs-dev/rst/images/inport_transitions.png b/akka-docs/rst/images/inport_transitions.png similarity index 100% rename from akka-docs-dev/rst/images/inport_transitions.png rename to akka-docs/rst/images/inport_transitions.png diff --git a/akka-docs-dev/rst/images/outport_transitions.png b/akka-docs/rst/images/outport_transitions.png similarity index 100% rename from akka-docs-dev/rst/images/outport_transitions.png rename to akka-docs/rst/images/outport_transitions.png diff --git a/akka-docs-dev/rst/images/port_transitions.svg b/akka-docs/rst/images/port_transitions.svg similarity index 100% rename from akka-docs-dev/rst/images/port_transitions.svg rename to akka-docs/rst/images/port_transitions.svg diff --git a/akka-docs-dev/rst/images/simple-graph-example.png b/akka-docs/rst/images/simple-graph-example.png similarity index 100% rename from akka-docs-dev/rst/images/simple-graph-example.png rename to akka-docs/rst/images/simple-graph-example.png diff --git a/akka-docs-dev/rst/images/stage_chain.png b/akka-docs/rst/images/stage_chain.png similarity index 100% rename from akka-docs-dev/rst/images/stage_chain.png rename to akka-docs/rst/images/stage_chain.png diff --git a/akka-docs-dev/rst/images/stage_conceptual.png b/akka-docs/rst/images/stage_conceptual.png similarity index 100% rename from akka-docs-dev/rst/images/stage_conceptual.png rename to akka-docs/rst/images/stage_conceptual.png diff --git a/akka-docs-dev/rst/images/stage_doubler.png b/akka-docs/rst/images/stage_doubler.png similarity index 100% rename from akka-docs-dev/rst/images/stage_doubler.png rename to akka-docs/rst/images/stage_doubler.png diff --git a/akka-docs-dev/rst/images/stage_filter.png b/akka-docs/rst/images/stage_filter.png similarity index 100% rename from akka-docs-dev/rst/images/stage_filter.png rename to akka-docs/rst/images/stage_filter.png diff --git a/akka-docs-dev/rst/images/stage_map.png b/akka-docs/rst/images/stage_map.png similarity index 100% rename from akka-docs-dev/rst/images/stage_map.png rename to akka-docs/rst/images/stage_map.png diff --git a/akka-docs-dev/rst/images/stage_msc_absorb_1.png b/akka-docs/rst/images/stage_msc_absorb_1.png similarity index 100% rename from akka-docs-dev/rst/images/stage_msc_absorb_1.png rename to akka-docs/rst/images/stage_msc_absorb_1.png diff --git a/akka-docs-dev/rst/images/stage_msc_absorb_2.png b/akka-docs/rst/images/stage_msc_absorb_2.png similarity index 100% rename from akka-docs-dev/rst/images/stage_msc_absorb_2.png rename to akka-docs/rst/images/stage_msc_absorb_2.png diff --git a/akka-docs-dev/rst/images/stage_msc_buffer.png b/akka-docs/rst/images/stage_msc_buffer.png similarity index 100% rename from akka-docs-dev/rst/images/stage_msc_buffer.png rename to akka-docs/rst/images/stage_msc_buffer.png diff --git a/akka-docs-dev/rst/images/stage_msc_general.png b/akka-docs/rst/images/stage_msc_general.png similarity index 100% rename from akka-docs-dev/rst/images/stage_msc_general.png rename to akka-docs/rst/images/stage_msc_general.png diff --git a/akka-docs-dev/rst/images/stages.svg b/akka-docs/rst/images/stages.svg similarity index 100% rename from akka-docs-dev/rst/images/stages.svg rename to akka-docs/rst/images/stages.svg diff --git a/akka-docs-dev/rst/images/stages_sequence_charts.svg b/akka-docs/rst/images/stages_sequence_charts.svg similarity index 100% rename from akka-docs-dev/rst/images/stages_sequence_charts.svg rename to akka-docs/rst/images/stages_sequence_charts.svg diff --git a/akka-docs/rst/java.rst b/akka-docs/rst/java.rst index 18d8569efb..af63887894 100644 --- a/akka-docs/rst/java.rst +++ b/akka-docs/rst/java.rst @@ -13,6 +13,8 @@ Java Documentation java/index-futures java/index-network java/index-utilities + java/stream/index + java/http/index java/howto experimental/index-java dev/index diff --git a/akka-docs/rst/java/code/docs/actor/ActorDocTest.java b/akka-docs/rst/java/code/docs/actor/ActorDocTest.java new file mode 100644 index 0000000000..206072f7b4 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/ActorDocTest.java @@ -0,0 +1,639 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +import akka.actor.*; +import akka.japi.pf.ReceiveBuilder; +import akka.testkit.ErrorFilter; +import akka.testkit.EventFilter; +import akka.testkit.TestEvent; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import scala.PartialFunction; +import scala.runtime.BoxedUnit; +import static docs.actor.Messages.Swap.Swap; +import static docs.actor.Messages.*; +import static akka.japi.Util.immutableSeq; + +import java.util.concurrent.TimeUnit; + +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +//#import-props +import akka.actor.Props; +//#import-props +//#import-actorRef +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +//#import-actorRef +//#import-identify +import akka.actor.ActorIdentity; +import akka.actor.ActorSelection; +import akka.actor.Identify; +//#import-identify +//#import-graceFulStop +import akka.pattern.AskTimeoutException; +import scala.concurrent.Await; +import scala.concurrent.duration.Duration; +import scala.concurrent.Future; +import static akka.pattern.Patterns.gracefulStop; +//#import-graceFulStop + +public class ActorDocTest { + + public static Config config = ConfigFactory.parseString( + "akka {\n" + + " loggers = [\"akka.testkit.TestEventListener\"]\n" + + " loglevel = \"WARNING\"\n" + + " stdout-loglevel = \"WARNING\"\n" + + "}\n" + ); + + static ActorSystem system = null; + + @BeforeClass + public static void beforeClass() { + system = ActorSystem.create("ActorDocTest", config); + } + + @AfterClass + public static void afterClass() { + system.shutdown(); + system.awaitTermination(Duration.create("5 seconds")); + } + + static + //#context-actorOf + public class FirstActor extends AbstractActor { + final ActorRef child = context().actorOf(Props.create(MyActor.class), "myChild"); + //#plus-some-behavior + public FirstActor() { + receive(ReceiveBuilder. + matchAny(x -> { + sender().tell(x, self()); + }).build() + ); + } + //#plus-some-behavior + } + //#context-actorOf + + static public abstract class SomeActor extends AbstractActor { + //#receive-constructor + public SomeActor() { + receive(ReceiveBuilder. + //#and-some-behavior + match(String.class, s -> System.out.println(s.toLowerCase())). + //#and-some-behavior + build()); + } + //#receive-constructor + @Override + //#receive + public abstract PartialFunction receive(); + //#receive + } + + static public class ActorWithArgs extends AbstractActor { + private final String args; + + ActorWithArgs(String args) { + this.args = args; + receive(ReceiveBuilder. + matchAny(x -> { }).build() + ); + } + } + + static + //#props-factory + public class DemoActor extends AbstractActor { + /** + * Create Props for an actor of this type. + * @param magicNumber The magic number to be passed to this actor’s constructor. + * @return a Props for creating this actor, which can then be further configured + * (e.g. calling `.withDispatcher()` on it) + */ + static Props props(Integer magicNumber) { + // You need to specify the actual type of the returned actor + // since Java 8 lambdas have some runtime type information erased + return Props.create(DemoActor.class, () -> new DemoActor(magicNumber)); + } + + private final Integer magicNumber; + + DemoActor(Integer magicNumber) { + this.magicNumber = magicNumber; + receive(ReceiveBuilder. + match(Integer.class, i -> { + sender().tell(i + magicNumber, self()); + }).build() + ); + } + } + + //#props-factory + static + //#props-factory + public class SomeOtherActor extends AbstractActor { + // Props(new DemoActor(42)) would not be safe + ActorRef demoActor = context().actorOf(DemoActor.props(42), "demo"); + // ... + //#props-factory + public SomeOtherActor() { + receive(emptyBehavior()); + } + //#props-factory + } + //#props-factory + + public static class Hook extends AbstractActor { + ActorRef target = null; + public Hook() { + receive(emptyBehavior()); + } + //#preStart + @Override + public void preStart() { + target = context().actorOf(Props.create(MyActor.class, "target")); + } + //#preStart + //#postStop + @Override + public void postStop() { + //#clean-up-some-resources + final String message = "stopped"; + //#tell + // don’t forget to think about who is the sender (2nd argument) + target.tell(message, self()); + //#tell + final Object result = ""; + //#forward + target.forward(result, context()); + //#forward + target = null; + //#clean-up-some-resources + } + //#postStop + + // compilation test only + public void compileSelections() { + //#selection-local + // will look up this absolute path + context().actorSelection("/user/serviceA/actor"); + // will look up sibling beneath same supervisor + context().actorSelection("../joe"); + //#selection-local + + //#selection-wildcard + // will look all children to serviceB with names starting with worker + context().actorSelection("/user/serviceB/worker*"); + // will look up all siblings beneath same supervisor + context().actorSelection("../*"); + //#selection-wildcard + + //#selection-remote + context().actorSelection("akka.tcp://app@otherhost:1234/user/serviceB"); + //#selection-remote + } + } + + public static class ReplyException extends AbstractActor { + public ReplyException() { + receive(ReceiveBuilder. + matchAny(x -> { + //#reply-exception + try { + String result = operation(); + sender().tell(result, self()); + } catch (Exception e) { + sender().tell(new akka.actor.Status.Failure(e), self()); + throw e; + } + //#reply-exception + }).build() + ); + } + + private String operation() { + return "Hi"; + } + } + + static + //#gracefulStop-actor + public class Manager extends AbstractActor { + private static enum Shutdown { + Shutdown + } + public static final Shutdown SHUTDOWN = Shutdown.Shutdown; + + private ActorRef worker = + context().watch(context().actorOf(Props.create(Cruncher.class), "worker")); + + public Manager() { + receive(ReceiveBuilder. + matchEquals("job", s -> { + worker.tell("crunch", self()); + }). + matchEquals(SHUTDOWN, x -> { + worker.tell(PoisonPill.getInstance(), self()); + context().become(shuttingDown); + }).build() + ); + } + + public PartialFunction shuttingDown = + ReceiveBuilder. + matchEquals("job", s -> { + sender().tell("service unavailable, shutting down", self()); + }). + match(Terminated.class, t -> t.actor().equals(worker), t -> { + context().stop(self()); + }).build(); + } + //#gracefulStop-actor + + @Test + public void usePatternsGracefulStop() throws Exception { + ActorRef actorRef = system.actorOf(Props.create(Manager.class)); + //#gracefulStop + try { + Future stopped = + gracefulStop(actorRef, Duration.create(5, TimeUnit.SECONDS), Manager.SHUTDOWN); + Await.result(stopped, Duration.create(6, TimeUnit.SECONDS)); + // the actor has been stopped + } catch (AskTimeoutException e) { + // the actor wasn't stopped within 5 seconds + } + //#gracefulStop + } + + + public static class Cruncher extends AbstractActor { + public Cruncher() { + receive(ReceiveBuilder. + matchEquals("crunch", s -> { }).build() + ); + } + } + + static + //#swapper + public class Swapper extends AbstractLoggingActor { + public Swapper() { + receive(ReceiveBuilder. + matchEquals(Swap, s -> { + log().info("Hi"); + context().become(ReceiveBuilder. + matchEquals(Swap, x -> { + log().info("Ho"); + context().unbecome(); // resets the latest 'become' (just for fun) + }).build(), false); // push on top instead of replace + }).build() + ); + } + } + + //#swapper + static + //#swapper + public class SwapperApp { + public static void main(String[] args) { + ActorSystem system = ActorSystem.create("SwapperSystem"); + ActorRef swapper = system.actorOf(Props.create(Swapper.class), "swapper"); + swapper.tell(Swap, ActorRef.noSender()); // logs Hi + swapper.tell(Swap, ActorRef.noSender()); // logs Ho + swapper.tell(Swap, ActorRef.noSender()); // logs Hi + swapper.tell(Swap, ActorRef.noSender()); // logs Ho + swapper.tell(Swap, ActorRef.noSender()); // logs Hi + swapper.tell(Swap, ActorRef.noSender()); // logs Ho + system.shutdown(); + } + } + //#swapper + + + @Test + public void creatingActorWithSystemActorOf() { + //#system-actorOf + // ActorSystem is a heavy object: create only one per application + final ActorSystem system = ActorSystem.create("MySystem", config); + final ActorRef myActor = system.actorOf(Props.create(MyActor.class), "myactor"); + //#system-actorOf + try { + new JavaTestKit(system) { + { + myActor.tell("hello", getRef()); + expectMsgEquals("hello"); + } + }; + } finally { + JavaTestKit.shutdownActorSystem(system); + } + } + + @Test + public void creatingPropsConfig() { + //#creating-props + Props props1 = Props.create(MyActor.class); + Props props2 = Props.create(ActorWithArgs.class, + () -> new ActorWithArgs("arg")); // careful, see below + Props props3 = Props.create(ActorWithArgs.class, "arg"); + //#creating-props + + //#creating-props-deprecated + // NOT RECOMMENDED within another actor: + // encourages to close over enclosing class + Props props7 = Props.create(ActorWithArgs.class, + () -> new ActorWithArgs("arg")); + //#creating-props-deprecated + } + + @Test(expected=IllegalArgumentException.class) + public void creatingPropsIllegal() { + //#creating-props-illegal + // This will throw an IllegalArgumentException since some runtime + // type information of the lambda is erased. + // Use Props.create(actorClass, Creator) instead. + Props props = Props.create(() -> new ActorWithArgs("arg")); + //#creating-props-illegal + } + + static + //#receive-timeout + public class ReceiveTimeoutActor extends AbstractActor { + //#receive-timeout + ActorRef target = context().system().deadLetters(); + //#receive-timeout + public ReceiveTimeoutActor() { + // To set an initial delay + context().setReceiveTimeout(Duration.create("10 seconds")); + + receive(ReceiveBuilder. + matchEquals("Hello", s -> { + // To set in a response to a message + context().setReceiveTimeout(Duration.create("1 second")); + //#receive-timeout + target = sender(); + target.tell("Hello world", self()); + //#receive-timeout + }). + match(ReceiveTimeout.class, r -> { + // To turn it off + context().setReceiveTimeout(Duration.Undefined()); + //#receive-timeout + target.tell("timeout", self()); + //#receive-timeout + }).build() + ); + } + } + //#receive-timeout + + @Test + public void using_receiveTimeout() { + final ActorRef myActor = system.actorOf(Props.create(ReceiveTimeoutActor.class)); + new JavaTestKit(system) { + { + myActor.tell("Hello", getRef()); + expectMsgEquals("Hello world"); + expectMsgEquals("timeout"); + } + }; + } + + static + //#hot-swap-actor + public class HotSwapActor extends AbstractActor { + private PartialFunction angry; + private PartialFunction happy; + + public HotSwapActor() { + angry = + ReceiveBuilder. + matchEquals("foo", s -> { + sender().tell("I am already angry?", self()); + }). + matchEquals("bar", s -> { + context().become(happy); + }).build(); + + happy = ReceiveBuilder. + matchEquals("bar", s -> { + sender().tell("I am already happy :-)", self()); + }). + matchEquals("foo", s -> { + context().become(angry); + }).build(); + + receive(ReceiveBuilder. + matchEquals("foo", s -> { + context().become(angry); + }). + matchEquals("bar", s -> { + context().become(happy); + }).build() + ); + } + } + //#hot-swap-actor + + @Test + public void using_hot_swap() { + final ActorRef actor = system.actorOf(Props.create(HotSwapActor.class), "hot"); + new JavaTestKit(system) { + { + actor.tell("foo", getRef()); + actor.tell("foo", getRef()); + expectMsgEquals("I am already angry?"); + actor.tell("bar", getRef()); + actor.tell("bar", getRef()); + expectMsgEquals("I am already happy :-)"); + actor.tell("foo", getRef()); + actor.tell("foo", getRef()); + expectMsgEquals("I am already angry?"); + expectNoMsg(Duration.create(1, TimeUnit.SECONDS)); + } + }; + } + + + static + //#stash + public class ActorWithProtocol extends AbstractActorWithStash { + public ActorWithProtocol() { + receive(ReceiveBuilder. + matchEquals("open", s -> { + context().become(ReceiveBuilder. + matchEquals("write", ws -> { /* do writing */ }). + matchEquals("close", cs -> { + unstashAll(); + context().unbecome(); + }). + matchAny(msg -> stash()).build(), false); + }). + matchAny(msg -> stash()).build() + ); + } + } + //#stash + + @Test + public void using_Stash() { + final ActorRef actor = system.actorOf(Props.create(ActorWithProtocol.class), "stash"); + } + + static + //#watch + public class WatchActor extends AbstractActor { + private final ActorRef child = context().actorOf(Props.empty(), "target"); + private ActorRef lastSender = system.deadLetters(); + + public WatchActor() { + context().watch(child); // <-- this is the only call needed for registration + + receive(ReceiveBuilder. + matchEquals("kill", s -> { + context().stop(child); + lastSender = sender(); + }). + match(Terminated.class, t -> t.actor().equals(child), t -> { + lastSender.tell("finished", self()); + }).build() + ); + } + } + //#watch + + @Test + public void using_watch() { + ActorRef actor = system.actorOf(Props.create(WatchActor.class)); + + new JavaTestKit(system) { + { + actor.tell("kill", getRef()); + expectMsgEquals("finished"); + } + }; + } + + static + //#identify + public class Follower extends AbstractActor { + final Integer identifyId = 1; + + public Follower(){ + ActorSelection selection = context().actorSelection("/user/another"); + selection.tell(new Identify(identifyId), self()); + + receive(ReceiveBuilder. + match(ActorIdentity.class, id -> id.getRef() != null, id -> { + ActorRef ref = id.getRef(); + context().watch(ref); + context().become(active(ref)); + }). + match(ActorIdentity.class, id -> id.getRef() == null, id -> { + context().stop(self()); + }).build() + ); + } + + final PartialFunction active(final ActorRef another) { + return ReceiveBuilder. + match(Terminated.class, t -> t.actor().equals(another), t -> { + context().stop(self()); + }).build(); + } + } + //#identify + + @Test + public void using_Identify() { + ActorRef a = system.actorOf(Props.empty()); + ActorRef b = system.actorOf(Props.create(Follower.class)); + + new JavaTestKit(system) { + { + watch(b); + system.stop(a); + assertEquals(expectMsgClass(Duration.create(2, TimeUnit.SECONDS), Terminated.class).actor(), b); + } + }; + } + + public static class NoReceiveActor extends AbstractActor { + } + + @Test + public void noReceiveActor() { + EventFilter ex1 = new ErrorFilter(ActorInitializationException.class); + EventFilter[] ignoreExceptions = { ex1 }; + try { + system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions))); + new JavaTestKit(system) {{ + final ActorRef victim = new EventFilter(ActorInitializationException.class) { + protected ActorRef run() { + return system.actorOf(Props.create(NoReceiveActor.class), "victim"); + } + }.message("Actor behavior has not been set with receive(...)").occurrences(1).exec(); + + assertEquals(true, victim.isTerminated()); + }}; + } finally { + system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions))); + } + } + + public static class MultipleReceiveActor extends AbstractActor { + public MultipleReceiveActor() { + receive(ReceiveBuilder. + match(String.class, s1 -> s1.toLowerCase().equals("become"), s1 -> { + sender().tell(s1.toUpperCase(), self()); + receive(ReceiveBuilder. + match(String.class, s2 -> { + sender().tell(s2.toLowerCase(), self()); + }).build() + ); + }). + match(String.class, s1 -> { + sender().tell(s1.toUpperCase(), self()); + }).build() + ); + } + } + + @Test + public void multipleReceiveActor() { + EventFilter ex1 = new ErrorFilter(IllegalActorStateException.class); + EventFilter[] ignoreExceptions = { ex1 }; + try { + system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions))); + new JavaTestKit(system) {{ + new EventFilter(IllegalActorStateException.class) { + protected Boolean run() { + ActorRef victim = system.actorOf(Props.create(MultipleReceiveActor.class), "victim2"); + victim.tell("Foo", getRef()); + expectMsgEquals("FOO"); + victim.tell("bEcoMe", getRef()); + expectMsgEquals("BECOME"); + victim.tell("Foo", getRef()); + // if it's upper case, then the actor was restarted + expectMsgEquals("FOO"); + return true; + } + }.message("Actor behavior has already been set with receive(...), " + + "use context().become(...) to change it later").occurrences(1).exec(); + }}; + } finally { + system.eventStream().publish(new TestEvent.UnMute(immutableSeq(ignoreExceptions))); + } + } + +} diff --git a/akka-docs/rst/java/code/docs/actor/FaultHandlingTestJava8.java b/akka-docs/rst/java/code/docs/actor/FaultHandlingTestJava8.java new file mode 100644 index 0000000000..6e4c02a7c1 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/FaultHandlingTestJava8.java @@ -0,0 +1,204 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ +package docs.actor; + +//#testkit +import akka.actor.*; + +import static akka.actor.SupervisorStrategy.resume; +import static akka.actor.SupervisorStrategy.restart; +import static akka.actor.SupervisorStrategy.stop; +import static akka.actor.SupervisorStrategy.escalate; +import akka.japi.pf.DeciderBuilder; +import akka.japi.pf.ReceiveBuilder; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import scala.PartialFunction; +import scala.concurrent.Await; +import static akka.pattern.Patterns.ask; +import scala.concurrent.duration.Duration; +import akka.testkit.TestProbe; + +//#testkit +import akka.testkit.ErrorFilter; +import akka.testkit.EventFilter; +import akka.testkit.TestEvent; +import akka.testkit.JavaTestKit; +import static java.util.concurrent.TimeUnit.SECONDS; +import static akka.japi.Util.immutableSeq; +import scala.Option; + +import org.junit.Test; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import scala.runtime.BoxedUnit; + +//#testkit +public class FaultHandlingTestJava8 { +//#testkit + + public static Config config = ConfigFactory.parseString( + "akka {\n" + + " loggers = [\"akka.testkit.TestEventListener\"]\n" + + " loglevel = \"WARNING\"\n" + + " stdout-loglevel = \"WARNING\"\n" + + "}\n"); + + static + //#supervisor + public class Supervisor extends AbstractActor { + + //#strategy + private static SupervisorStrategy strategy = + new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder. + match(ArithmeticException.class, e -> resume()). + match(NullPointerException.class, e -> restart()). + match(IllegalArgumentException.class, e -> stop()). + matchAny(o -> escalate()).build()); + + @Override + public SupervisorStrategy supervisorStrategy() { + return strategy; + } + + //#strategy + + public Supervisor() { + receive(ReceiveBuilder. + match(Props.class, props -> { + sender().tell(context().actorOf(props), self()); + }).build() + ); + } + } + + //#supervisor + + static + //#supervisor2 + public class Supervisor2 extends AbstractActor { + + //#strategy2 + private static SupervisorStrategy strategy = + new OneForOneStrategy(10, Duration.create("1 minute"), DeciderBuilder. + match(ArithmeticException.class, e -> resume()). + match(NullPointerException.class, e -> restart()). + match(IllegalArgumentException.class, e -> stop()). + matchAny(o -> escalate()).build()); + + @Override + public SupervisorStrategy supervisorStrategy() { + return strategy; + } + + //#strategy2 + + public Supervisor2() { + receive(ReceiveBuilder. + match(Props.class, props -> { + sender().tell(context().actorOf(props), self()); + }).build() + ); + } + + @Override + public void preRestart(Throwable cause, Option msg) { + // do not kill all children, which is the default here + } + } + + //#supervisor2 + + static + //#child + public class Child extends AbstractActor { + int state = 0; + + public Child() { + receive(ReceiveBuilder. + match(Exception.class, exception -> { throw exception; }). + match(Integer.class, i -> state = i). + matchEquals("get", s -> sender().tell(state, self())).build() + ); + } + } + + //#child + + //#testkit + static ActorSystem system; + Duration timeout = Duration.create(5, SECONDS); + + @BeforeClass + public static void start() { + system = ActorSystem.create("FaultHandlingTest", config); + } + + @AfterClass + public static void cleanup() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + @Test + public void mustEmploySupervisorStrategy() throws Exception { + // code here + //#testkit + EventFilter ex1 = new ErrorFilter(ArithmeticException.class); + EventFilter ex2 = new ErrorFilter(NullPointerException.class); + EventFilter ex3 = new ErrorFilter(IllegalArgumentException.class); + EventFilter ex4 = new ErrorFilter(Exception.class); + EventFilter[] ignoreExceptions = { ex1, ex2, ex3, ex4 }; + system.eventStream().publish(new TestEvent.Mute(immutableSeq(ignoreExceptions))); + + //#create + Props superprops = Props.create(Supervisor.class); + ActorRef supervisor = system.actorOf(superprops, "supervisor"); + ActorRef child = (ActorRef) Await.result(ask(supervisor, + Props.create(Child.class), 5000), timeout); + //#create + + //#resume + child.tell(42, ActorRef.noSender()); + assert Await.result(ask(child, "get", 5000), timeout).equals(42); + child.tell(new ArithmeticException(), ActorRef.noSender()); + assert Await.result(ask(child, "get", 5000), timeout).equals(42); + //#resume + + //#restart + child.tell(new NullPointerException(), ActorRef.noSender()); + assert Await.result(ask(child, "get", 5000), timeout).equals(0); + //#restart + + //#stop + final TestProbe probe = new TestProbe(system); + probe.watch(child); + child.tell(new IllegalArgumentException(), ActorRef.noSender()); + probe.expectMsgClass(Terminated.class); + //#stop + + //#escalate-kill + child = (ActorRef) Await.result(ask(supervisor, + Props.create(Child.class), 5000), timeout); + probe.watch(child); + assert Await.result(ask(child, "get", 5000), timeout).equals(0); + child.tell(new Exception(), ActorRef.noSender()); + probe.expectMsgClass(Terminated.class); + //#escalate-kill + + //#escalate-restart + superprops = Props.create(Supervisor2.class); + supervisor = system.actorOf(superprops); + child = (ActorRef) Await.result(ask(supervisor, + Props.create(Child.class), 5000), timeout); + child.tell(23, ActorRef.noSender()); + assert Await.result(ask(child, "get", 5000), timeout).equals(23); + child.tell(new Exception(), ActorRef.noSender()); + assert Await.result(ask(child, "get", 5000), timeout).equals(0); + //#escalate-restart + //#testkit + } + +} +//#testkit diff --git a/akka-docs/rst/java/code/docs/actor/InitializationDocTest.java b/akka-docs/rst/java/code/docs/actor/InitializationDocTest.java new file mode 100644 index 0000000000..67c22748b8 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/InitializationDocTest.java @@ -0,0 +1,67 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +import akka.actor.*; +import akka.japi.pf.ReceiveBuilder; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.PartialFunction; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; + +import java.util.concurrent.TimeUnit; + +public class InitializationDocTest { + + static ActorSystem system = null; + + @BeforeClass + public static void beforeClass() { + system = ActorSystem.create("InitializationDocTest"); + } + + @AfterClass + public static void afterClass() { + system.shutdown(); + system.awaitTermination(Duration.create("5 seconds")); + } + + public static class MessageInitExample extends AbstractActor { + private String initializeMe = null; + + public MessageInitExample() { + //#messageInit + receive(ReceiveBuilder. + matchEquals("init", m1 -> { + initializeMe = "Up and running"; + context().become(ReceiveBuilder. + matchEquals("U OK?", m2 -> { + sender().tell(initializeMe, self()); + }).build()); + }).build() + //#messageInit + ); + } + } + + @Test + public void testIt() { + + new JavaTestKit(system) {{ + ActorRef testactor = system.actorOf(Props.create(MessageInitExample.class), "testactor"); + String msg = "U OK?"; + + testactor.tell(msg, getRef()); + expectNoMsg(Duration.create(1, TimeUnit.SECONDS)); + + testactor.tell("init", getRef()); + testactor.tell(msg, getRef()); + expectMsgEquals("Up and running"); + }}; + } +} diff --git a/akka-docs/rst/java/code/docs/actor/Messages.java b/akka-docs/rst/java/code/docs/actor/Messages.java new file mode 100644 index 0000000000..150b65d9fc --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/Messages.java @@ -0,0 +1,149 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Messages { + static + //#immutable-message + public class ImmutableMessage { + private final int sequenceNumber; + private final List values; + + public ImmutableMessage(int sequenceNumber, List values) { + this.sequenceNumber = sequenceNumber; + this.values = Collections.unmodifiableList(new ArrayList(values)); + } + + public int getSequenceNumber() { + return sequenceNumber; + } + + public List getValues() { + return values; + } + } + //#immutable-message + + public static class DoIt { + private final ImmutableMessage msg; + + DoIt(ImmutableMessage msg) { + this.msg = msg; + } + + public ImmutableMessage getMsg() { + return msg; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DoIt doIt = (DoIt) o; + + if (!msg.equals(doIt.msg)) return false; + + return true; + } + + @Override + public int hashCode() { + return msg.hashCode(); + } + + @Override + public String toString() { + return "DoIt{" + + "msg=" + msg + + '}'; + } + } + + public static class Message { + final String str; + + Message(String str) { + this.str = str; + } + + public String getStr() { + return str; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Message message = (Message) o; + + if (!str.equals(message.str)) return false; + + return true; + } + + @Override + public int hashCode() { + return str.hashCode(); + } + + @Override + public String toString() { + return "Message{" + + "str='" + str + '\'' + + '}'; + } + } + + public static enum Swap { + Swap + } + + public static class Result { + final String x; + final String s; + + public Result(String x, String s) { + this.x = x; + this.s = s; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((s == null) ? 0 : s.hashCode()); + result = prime * result + ((x == null) ? 0 : x.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Result other = (Result) obj; + if (s == null) { + if (other.s != null) + return false; + } else if (!s.equals(other.s)) + return false; + if (x == null) { + if (other.x != null) + return false; + } else if (!x.equals(other.x)) + return false; + return true; + } + } +} diff --git a/akka-docs/rst/java/code/docs/actor/MyActor.java b/akka-docs/rst/java/code/docs/actor/MyActor.java new file mode 100644 index 0000000000..f77a1fa410 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/MyActor.java @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +//#imports +import akka.actor.AbstractActor; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import akka.japi.pf.ReceiveBuilder; + +//#imports + +//#my-actor +public class MyActor extends AbstractActor { + private final LoggingAdapter log = Logging.getLogger(context().system(), this); + + public MyActor() { + receive(ReceiveBuilder. + match(String.class, s -> { + log.info("Received String message: {}", s); + //#my-actor + //#reply + sender().tell(s, self()); + //#reply + //#my-actor + }). + matchAny(o -> log.info("received unknown message")).build() + ); + } +} +//#my-actor diff --git a/akka-docs/rst/java/code/docs/actor/SampleActor.java b/akka-docs/rst/java/code/docs/actor/SampleActor.java new file mode 100644 index 0000000000..61817c6d95 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/SampleActor.java @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +//#sample-actor +import akka.actor.AbstractActor; +import akka.japi.pf.ReceiveBuilder; +import scala.PartialFunction; +import scala.runtime.BoxedUnit; + +public class SampleActor extends AbstractActor { + + private PartialFunction guarded = ReceiveBuilder. + match(String.class, s -> s.contains("guard"), s -> { + sender().tell("contains(guard): " + s, self()); + context().unbecome(); + }).build(); + + public SampleActor() { + receive(ReceiveBuilder. + match(Double.class, d -> { + sender().tell(d.isNaN() ? 0 : d, self()); + }). + match(Integer.class, i -> { + sender().tell(i * 10, self()); + }). + match(String.class, s -> s.startsWith("guard"), s -> { + sender().tell("startsWith(guard): " + s.toUpperCase(), self()); + context().become(guarded, false); + }).build() + ); + } +} +//#sample-actor diff --git a/akka-docs/rst/java/code/docs/actor/SampleActorTest.java b/akka-docs/rst/java/code/docs/actor/SampleActorTest.java new file mode 100644 index 0000000000..5dff74f6e7 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/SampleActorTest.java @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class SampleActorTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("SampleActorTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + @Test + public void testSampleActor() + { + new JavaTestKit(system) {{ + final ActorRef subject = system.actorOf(Props.create(SampleActor.class), "sample-actor"); + final ActorRef probeRef = getRef(); + + subject.tell(47.11, probeRef); + subject.tell("and no guard in the beginning", probeRef); + subject.tell("guard is a good thing", probeRef); + subject.tell(47.11, probeRef); + subject.tell(4711, probeRef); + subject.tell("and no guard in the beginning", probeRef); + subject.tell(4711, probeRef); + subject.tell("and an unmatched message", probeRef); + + expectMsgEquals(47.11); + assertTrue(expectMsgClass(String.class).startsWith("startsWith(guard):")); + assertTrue(expectMsgClass(String.class).startsWith("contains(guard):")); + expectMsgEquals(47110); + expectNoMsg(); + }}; + } +} diff --git a/akka-docs/rst/java/code/docs/actor/fsm/Buncher.java b/akka-docs/rst/java/code/docs/actor/fsm/Buncher.java new file mode 100644 index 0000000000..335eb732f9 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/fsm/Buncher.java @@ -0,0 +1,136 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor.fsm; + +//#simple-imports +import akka.actor.AbstractFSM; +import akka.actor.ActorRef; +import akka.japi.pf.UnitMatch; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import scala.concurrent.duration.Duration; +//#simple-imports + +import static docs.actor.fsm.Buncher.Data; +import static docs.actor.fsm.Buncher.State.*; +import static docs.actor.fsm.Buncher.State; +import static docs.actor.fsm.Buncher.Uninitialized.*; +import static docs.actor.fsm.Events.*; + +//#simple-fsm +public class Buncher extends AbstractFSM { + { + //#fsm-body + startWith(Idle, Uninitialized); + + //#when-syntax + when(Idle, + matchEvent(SetTarget.class, Uninitialized.class, + (setTarget, uninitialized) -> + stay().using(new Todo(setTarget.getRef(), new LinkedList<>())))); + //#when-syntax + + //#transition-elided + onTransition( + matchState(Active, Idle, () -> { + // reuse this matcher + final UnitMatch m = UnitMatch.create( + matchData(Todo.class, + todo -> todo.getTarget().tell(new Batch(todo.getQueue()), self()))); + m.match(stateData()); + }). + state(Idle, Active, () -> {/* Do something here */})); + //#transition-elided + + when(Active, Duration.create(1, "second"), + matchEvent(Arrays.asList(Flush.class, StateTimeout()), Todo.class, + (event, todo) -> goTo(Idle).using(todo.copy(new LinkedList<>())))); + + //#unhandled-elided + whenUnhandled( + matchEvent(Queue.class, Todo.class, + (queue, todo) -> goTo(Active).using(todo.addElement(queue.getObj()))). + anyEvent((event, state) -> { + log().warning("received unhandled request {} in state {}/{}", + event, stateName(), state); + return stay(); + })); + //#unhandled-elided + + initialize(); + //#fsm-body + } + //#simple-fsm + + static + //#simple-state + // states + enum State { + Idle, Active + } + + //#simple-state + static + //#simple-state + // state data + interface Data { + } + + //#simple-state + static + //#simple-state + enum Uninitialized implements Data { + Uninitialized + } + + //#simple-state + static + //#simple-state + final class Todo implements Data { + private final ActorRef target; + private final List queue; + + public Todo(ActorRef target, List queue) { + this.target = target; + this.queue = queue; + } + + public ActorRef getTarget() { + return target; + } + + public List getQueue() { + return queue; + } + //#boilerplate + + @Override + public String toString() { + return "Todo{" + + "target=" + target + + ", queue=" + queue + + '}'; + } + + public Todo addElement(Object element) { + List nQueue = new LinkedList<>(queue); + nQueue.add(element); + return new Todo(this.target, nQueue); + } + + public Todo copy(List queue) { + return new Todo(this.target, queue); + } + + public Todo copy(ActorRef target) { + return new Todo(target, this.queue); + } + //#boilerplate + } + //#simple-state + //#simple-fsm +} +//#simple-fsm diff --git a/akka-docs/rst/java/code/docs/actor/fsm/BuncherTest.java b/akka-docs/rst/java/code/docs/actor/fsm/BuncherTest.java new file mode 100644 index 0000000000..22990a446a --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/fsm/BuncherTest.java @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor.fsm; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import java.util.LinkedList; + +import docs.actor.fsm.*; +import static docs.actor.fsm.Events.Batch; +import static docs.actor.fsm.Events.Queue; +import static docs.actor.fsm.Events.SetTarget; +import static docs.actor.fsm.Events.Flush.Flush; + +//#test-code +public class BuncherTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("BuncherTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + @Test + public void testBuncherActorBatchesCorrectly() { + new JavaTestKit(system) {{ + final ActorRef buncher = + system.actorOf(Props.create(Buncher.class)); + final ActorRef probe = getRef(); + + buncher.tell(new SetTarget(probe), probe); + buncher.tell(new Queue(42), probe); + buncher.tell(new Queue(43), probe); + LinkedList list1 = new LinkedList<>(); + list1.add(42); + list1.add(43); + expectMsgEquals(new Batch(list1)); + buncher.tell(new Queue(44), probe); + buncher.tell(Flush, probe); + buncher.tell(new Queue(45), probe); + LinkedList list2 = new LinkedList<>(); + list2.add(44); + expectMsgEquals(new Batch(list2)); + LinkedList list3 = new LinkedList<>(); + list3.add(45); + expectMsgEquals(new Batch(list3)); + system.stop(buncher); + }}; + } + + @Test + public void testBuncherActorDoesntBatchUninitialized() { + new JavaTestKit(system) {{ + final ActorRef buncher = + system.actorOf(Props.create(Buncher.class)); + final ActorRef probe = getRef(); + + buncher.tell(new Queue(42), probe); + expectNoMsg(); + system.stop(buncher); + }}; + } +} +//#test-code diff --git a/akka-docs/rst/java/code/docs/actor/fsm/Events.java b/akka-docs/rst/java/code/docs/actor/fsm/Events.java new file mode 100644 index 0000000000..a50d18d590 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/fsm/Events.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor.fsm; + +import akka.actor.ActorRef; +import java.util.List; + +public class Events { + + static + //#simple-events + public final class SetTarget { + private final ActorRef ref; + + public SetTarget(ActorRef ref) { + this.ref = ref; + } + + public ActorRef getRef() { + return ref; + } + //#boilerplate + + @Override + public String toString() { + return "SetTarget{" + + "ref=" + ref + + '}'; + } + //#boilerplate + } + + //#simple-events + static + //#simple-events + public final class Queue { + private final Object obj; + + public Queue(Object obj) { + this.obj = obj; + } + + public Object getObj() { + return obj; + } + //#boilerplate + + @Override + public String toString() { + return "Queue{" + + "obj=" + obj + + '}'; + } + //#boilerplate + } + + //#simple-events + static + //#simple-events + public final class Batch { + private final List list; + + public Batch(List list) { + this.list = list; + } + + public List getList() { + return list; + } + //#boilerplate + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Batch batch = (Batch) o; + + return list.equals(batch.list); + } + + @Override + public int hashCode() { + return list.hashCode(); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append( "Batch{list="); + list.stream().forEachOrdered(e -> { builder.append(e); builder.append(","); }); + int len = builder.length(); + builder.replace(len, len, "}"); + return builder.toString(); + } + //#boilerplate + } + + //#simple-events + static + //#simple-events + public enum Flush { + Flush + } + //#simple-events +} diff --git a/akka-docs/rst/java/code/docs/actor/fsm/FSMDocTest.java b/akka-docs/rst/java/code/docs/actor/fsm/FSMDocTest.java new file mode 100644 index 0000000000..57c7a21e84 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/fsm/FSMDocTest.java @@ -0,0 +1,179 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package docs.actor.fsm; + +import akka.actor.*; +import akka.testkit.JavaTestKit; +import org.hamcrest.CoreMatchers; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.duration.Duration; + +import static org.junit.Assert.*; + +import static docs.actor.fsm.FSMDocTest.StateType.*; +import static docs.actor.fsm.FSMDocTest.Messages.*; +import static java.util.concurrent.TimeUnit.*; + +public class FSMDocTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FSMDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + public static enum StateType { + SomeState, + Processing, + Idle, + Active, + Error + } + + public static enum Messages { + WillDo, + Tick + } + + public static enum Data { + Foo, + Bar + }; + + public static interface X {}; + + public static class DummyFSM extends AbstractFSM { + Integer newData = 42; + //#alt-transition-syntax + public void handler(StateType from, StateType to) { + // handle transition here + } + + //#alt-transition-syntax + { + //#modifier-syntax + when(SomeState, matchAnyEvent((msg, data) -> { + return goTo(Processing).using(newData). + forMax(Duration.create(5, SECONDS)).replying(WillDo); + })); + //#modifier-syntax + + //#NullFunction + when(SomeState, AbstractFSM.NullFunction()); + //#NullFunction + + //#transition-syntax + onTransition( + matchState(Active, Idle, () -> setTimer("timeout", + Tick, Duration.create(1, SECONDS), true)). + state(Active, null, () -> cancelTimer("timeout")). + state(null, Idle, (f, t) -> log().info("entering Idle from " + f))); + //#transition-syntax + + //#alt-transition-syntax + onTransition(this::handler); + //#alt-transition-syntax + + //#stop-syntax + when(Error, matchEventEquals("stop", (event, data) -> { + // do cleanup ... + return stop(); + })); + //#stop-syntax + + //#termination-syntax + onTermination( + matchStop(Normal(), + (state, data) -> {/* Do something here */}). + stop(Shutdown(), + (state, data) -> {/* Do something here */}). + stop(Failure.class, + (reason, state, data) -> {/* Do something here */})); + //#termination-syntax + + //#unhandled-syntax + whenUnhandled( + matchEvent(X.class, (x, data) -> { + log().info("Received unhandled event: " + x); + return stay(); + }). + anyEvent((event, data) -> { + log().warning("Received unknown event: " + event); + return goTo(Error); + })); + } + //#unhandled-syntax + } + + static + //#logging-fsm + public class MyFSM extends AbstractLoggingFSM { + //#body-elided + //#logging-fsm + ActorRef target = null; + //#logging-fsm + @Override + public int logDepth() { return 12; } + { + onTermination( + matchStop(Failure.class, (reason, state, data) -> { + String lastEvents = getLog().mkString("\n\t"); + log().warning("Failure in state " + state + " with data " + data + "\n" + + "Events leading up to this point:\n\t" + lastEvents); + //#logging-fsm + target.tell(reason.cause(), self()); + target.tell(state, self()); + target.tell(data, self()); + target.tell(lastEvents, self()); + //#logging-fsm + }) + ); + //... + //#logging-fsm + startWith(SomeState, Data.Foo); + when(SomeState, matchEvent(ActorRef.class, Data.class, (ref, data) -> { + target = ref; + target.tell("going active", self()); + return goTo(Active); + })); + when(Active, matchEventEquals("stop", (event, data) -> { + target.tell("stopping", self()); + return stop(new Failure("This is not the error you're looking for")); + })); + initialize(); + //#logging-fsm + } + //#body-elided + } + //#logging-fsm + + @Test + public void testLoggingFSM() + { + new JavaTestKit(system) {{ + final ActorRef logger = + system.actorOf(Props.create(MyFSM.class)); + final ActorRef probe = getRef(); + + logger.tell(probe, probe); + expectMsgEquals("going active"); + logger.tell("stop", probe); + expectMsgEquals("stopping"); + expectMsgEquals("This is not the error you're looking for"); + expectMsgEquals(Active); + expectMsgEquals(Data.Foo); + String msg = expectMsgClass(String.class); + assertThat(msg, CoreMatchers.startsWith("LogEntry(SomeState,Foo,Actor[akka://FSMDocTest/system/")); + }}; + } +} diff --git a/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSampleJava8.java b/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSampleJava8.java new file mode 100644 index 0000000000..73b15a5e75 --- /dev/null +++ b/akka-docs/rst/java/code/docs/actor/japi/FaultHandlingDocSampleJava8.java @@ -0,0 +1,470 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ +package docs.actor.japi; + +//#all +//#imports +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import akka.actor.*; +import akka.dispatch.Mapper; +import akka.event.LoggingReceive; +import akka.japi.pf.DeciderBuilder; +import akka.japi.pf.ReceiveBuilder; +import akka.util.Timeout; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import scala.concurrent.duration.Duration; +import scala.PartialFunction; +import scala.runtime.BoxedUnit; + +import static akka.japi.Util.classTag; +import static akka.actor.SupervisorStrategy.resume; +import static akka.actor.SupervisorStrategy.restart; +import static akka.actor.SupervisorStrategy.stop; +import static akka.actor.SupervisorStrategy.escalate; + +import static akka.pattern.Patterns.ask; +import static akka.pattern.Patterns.pipe; + +import static docs.actor.japi.FaultHandlingDocSample.WorkerApi.*; +import static docs.actor.japi.FaultHandlingDocSample.CounterServiceApi.*; +import static docs.actor.japi.FaultHandlingDocSample.CounterApi.*; +import static docs.actor.japi.FaultHandlingDocSample.StorageApi.*; + +//#imports + +public class FaultHandlingDocSampleJava8 { + + /** + * Runs the sample + */ + public static void main(String[] args) { + Config config = ConfigFactory.parseString( + "akka.loglevel = \"DEBUG\"\n" + + "akka.actor.debug {\n" + + " receive = on\n" + + " lifecycle = on\n" + + "}\n"); + + ActorSystem system = ActorSystem.create("FaultToleranceSample", config); + ActorRef worker = system.actorOf(Props.create(Worker.class), "worker"); + ActorRef listener = system.actorOf(Props.create(Listener.class), "listener"); + // start the work and listen on progress + // note that the listener is used as sender of the tell, + // i.e. it will receive replies from the worker + worker.tell(Start, listener); + } + + /** + * Listens on progress from the worker and shuts down the system when enough + * work has been done. + */ + public static class Listener extends AbstractLoggingActor { + + @Override + public void preStart() { + // If we don't get any progress within 15 seconds then the service + // is unavailable + context().setReceiveTimeout(Duration.create("15 seconds")); + } + + public Listener() { + receive(LoggingReceive.create(ReceiveBuilder. + match(Progress.class, progress -> { + log().info("Current progress: {} %", progress.percent); + if (progress.percent >= 100.0) { + log().info("That's all, shutting down"); + context().system().shutdown(); + } + }). + matchEquals(ReceiveTimeout.getInstance(), x -> { + // No progress within 15 seconds, ServiceUnavailable + log().error("Shutting down due to unavailable service"); + context().system().shutdown(); + }).build(), context() + )); + } + } + + //#messages + public interface WorkerApi { + public static final Object Start = "Start"; + public static final Object Do = "Do"; + + public static class Progress { + public final double percent; + + public Progress(double percent) { + this.percent = percent; + } + + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), percent); + } + } + } + + //#messages + + /** + * Worker performs some work when it receives the Start message. It will + * continuously notify the sender of the Start message of current Progress. + * The Worker supervise the CounterService. + */ + public static class Worker extends AbstractLoggingActor { + final Timeout askTimeout = new Timeout(Duration.create(5, "seconds")); + + // The sender of the initial Start message will continuously be notified + // about progress + ActorRef progressListener; + final ActorRef counterService = context().actorOf( + Props.create(CounterService.class), "counter"); + final int totalCount = 51; + + // Stop the CounterService child if it throws ServiceUnavailable + private static final SupervisorStrategy strategy = + new OneForOneStrategy(DeciderBuilder. + match(ServiceUnavailable.class, e -> stop()). + matchAny(o -> escalate()).build()); + + @Override + public SupervisorStrategy supervisorStrategy() { + return strategy; + } + + public Worker() { + receive(LoggingReceive.create(ReceiveBuilder. + matchEquals(Start, x -> progressListener == null, x -> { + progressListener = sender(); + context().system().scheduler().schedule( + Duration.Zero(), Duration.create(1, "second"), self(), Do, + context().dispatcher(), null + ); + }). + matchEquals(Do, x -> { + counterService.tell(new Increment(1), self()); + counterService.tell(new Increment(1), self()); + counterService.tell(new Increment(1), self()); + // Send current progress to the initial sender + pipe(ask(counterService, GetCurrentCount, askTimeout) + .mapTo(classTag(CurrentCount.class)) + .map(new Mapper() { + public Progress apply(CurrentCount c) { + return new Progress(100.0 * c.count / totalCount); + } + }, context().dispatcher()), context().dispatcher()) + .to(progressListener); + }).build(), context()) + ); + } + } + + //#messages + public interface CounterServiceApi { + + public static final Object GetCurrentCount = "GetCurrentCount"; + + public static class CurrentCount { + public final String key; + public final long count; + + public CurrentCount(String key, long count) { + this.key = key; + this.count = count; + } + + public String toString() { + return String.format("%s(%s, %s)", getClass().getSimpleName(), key, count); + } + } + + public static class Increment { + public final long n; + + public Increment(long n) { + this.n = n; + } + + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), n); + } + } + + public static class ServiceUnavailable extends RuntimeException { + private static final long serialVersionUID = 1L; + public ServiceUnavailable(String msg) { + super(msg); + } + } + + } + + //#messages + + /** + * Adds the value received in Increment message to a persistent counter. + * Replies with CurrentCount when it is asked for CurrentCount. CounterService + * supervise Storage and Counter. + */ + public static class CounterService extends AbstractLoggingActor { + + // Reconnect message + static final Object Reconnect = "Reconnect"; + + private static class SenderMsgPair { + final ActorRef sender; + final Object msg; + + SenderMsgPair(ActorRef sender, Object msg) { + this.msg = msg; + this.sender = sender; + } + } + + final String key = self().path().name(); + ActorRef storage; + ActorRef counter; + final List backlog = new ArrayList<>(); + final int MAX_BACKLOG = 10000; + + // Restart the storage child when StorageException is thrown. + // After 3 restarts within 5 seconds it will be stopped. + private static final SupervisorStrategy strategy = + new OneForOneStrategy(3, Duration.create("5 seconds"), DeciderBuilder. + match(StorageException.class, e -> restart()). + matchAny(o -> escalate()).build()); + + @Override + public SupervisorStrategy supervisorStrategy() { + return strategy; + } + + @Override + public void preStart() { + initStorage(); + } + + /** + * The child storage is restarted in case of failure, but after 3 restarts, + * and still failing it will be stopped. Better to back-off than + * continuously failing. When it has been stopped we will schedule a + * Reconnect after a delay. Watch the child so we receive Terminated message + * when it has been terminated. + */ + void initStorage() { + storage = context().watch(context().actorOf( + Props.create(Storage.class), "storage")); + // Tell the counter, if any, to use the new storage + if (counter != null) + counter.tell(new UseStorage(storage), self()); + // We need the initial value to be able to operate + storage.tell(new Get(key), self()); + } + + public CounterService() { + receive(LoggingReceive.create(ReceiveBuilder. + match(Entry.class, entry -> entry.key.equals(key) && counter == null, entry -> { + // Reply from Storage of the initial value, now we can create the Counter + final long value = entry.value; + counter = context().actorOf(Props.create(Counter.class, key, value)); + // Tell the counter to use current storage + counter.tell(new UseStorage(storage), self()); + // and send the buffered backlog to the counter + for (SenderMsgPair each : backlog) { + counter.tell(each.msg, each.sender); + } + backlog.clear(); + }). + match(Increment.class, increment -> { + forwardOrPlaceInBacklog(increment); + }). + matchEquals(GetCurrentCount, gcc -> { + forwardOrPlaceInBacklog(gcc); + }). + match(Terminated.class, o -> { + // After 3 restarts the storage child is stopped. + // We receive Terminated because we watch the child, see initStorage. + storage = null; + // Tell the counter that there is no storage for the moment + counter.tell(new UseStorage(null), self()); + // Try to re-establish storage after while + context().system().scheduler().scheduleOnce( + Duration.create(10, "seconds"), self(), Reconnect, + context().dispatcher(), null); + }). + matchEquals(Reconnect, o -> { + // Re-establish storage after the scheduled delay + initStorage(); + }).build(), context()) + ); + } + + void forwardOrPlaceInBacklog(Object msg) { + // We need the initial value from storage before we can start delegate to + // the counter. Before that we place the messages in a backlog, to be sent + // to the counter when it is initialized. + if (counter == null) { + if (backlog.size() >= MAX_BACKLOG) + throw new ServiceUnavailable("CounterService not available," + + " lack of initial value"); + backlog.add(new SenderMsgPair(sender(), msg)); + } else { + counter.forward(msg, context()); + } + } + } + + //#messages + public interface CounterApi { + public static class UseStorage { + public final ActorRef storage; + + public UseStorage(ActorRef storage) { + this.storage = storage; + } + + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), storage); + } + } + } + + //#messages + + /** + * The in memory count variable that will send current value to the Storage, + * if there is any storage available at the moment. + */ + public static class Counter extends AbstractLoggingActor { + final String key; + long count; + ActorRef storage; + + public Counter(String key, long initialValue) { + this.key = key; + this.count = initialValue; + + receive(LoggingReceive.create(ReceiveBuilder. + match(UseStorage.class, useStorage -> { + storage = useStorage.storage; + storeCount(); + }). + match(Increment.class, increment -> { + count += increment.n; + storeCount(); + }). + matchEquals(GetCurrentCount, gcc -> { + sender().tell(new CurrentCount(key, count), self()); + }).build(), context()) + ); + } + + void storeCount() { + // Delegate dangerous work, to protect our valuable state. + // We can continue without storage. + if (storage != null) { + storage.tell(new Store(new Entry(key, count)), self()); + } + } + } + + //#messages + public interface StorageApi { + + public static class Store { + public final Entry entry; + + public Store(Entry entry) { + this.entry = entry; + } + + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), entry); + } + } + + public static class Entry { + public final String key; + public final long value; + + public Entry(String key, long value) { + this.key = key; + this.value = value; + } + + public String toString() { + return String.format("%s(%s, %s)", getClass().getSimpleName(), key, value); + } + } + + public static class Get { + public final String key; + + public Get(String key) { + this.key = key; + } + + public String toString() { + return String.format("%s(%s)", getClass().getSimpleName(), key); + } + } + + public static class StorageException extends RuntimeException { + private static final long serialVersionUID = 1L; + public StorageException(String msg) { + super(msg); + } + } + } + + //#messages + + /** + * Saves key/value pairs to persistent storage when receiving Store message. + * Replies with current value when receiving Get message. Will throw + * StorageException if the underlying data store is out of order. + */ + public static class Storage extends AbstractLoggingActor { + + final DummyDB db = DummyDB.instance; + + public Storage() { + receive(LoggingReceive.create(ReceiveBuilder. + match(Store.class, store -> { + db.save(store.entry.key, store.entry.value); + }). + match(Get.class, get -> { + Long value = db.load(get.key); + sender().tell(new Entry(get.key, value == null ? + Long.valueOf(0L) : value), self()); + }).build(), context()) + ); + } + } + + //#dummydb + public static class DummyDB { + public static final DummyDB instance = new DummyDB(); + private final Map db = new HashMap(); + + private DummyDB() { + } + + public synchronized void save(String key, Long value) throws StorageException { + if (11 <= value && value <= 14) + throw new StorageException("Simulated store failure " + value); + db.put(key, value); + } + + public synchronized Long load(String key) throws StorageException { + return db.get(key); + } + } + //#dummydb +} +//#all diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/HttpClientExampleDocTest.java b/akka-docs/rst/java/code/docs/http/javadsl/HttpClientExampleDocTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/HttpClientExampleDocTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/HttpClientExampleDocTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/ModelDocTest.java b/akka-docs/rst/java/code/docs/http/javadsl/ModelDocTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/ModelDocTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/ModelDocTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HighLevelServerExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/HighLevelServerExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/HighLevelServerExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/HighLevelServerExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HttpBasicAuthenticatorExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/HttpBasicAuthenticatorExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/HttpBasicAuthenticatorExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/HttpBasicAuthenticatorExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HttpServerExampleDocTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/HttpServerExampleDocTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/HttpServerExampleDocTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/HttpServerExampleDocTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/OAuth2AuthenticatorExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/OAuth2AuthenticatorExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/OAuth2AuthenticatorExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/OAuth2AuthenticatorExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/PathDirectiveExampleTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/PathDirectiveExampleTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/PathDirectiveExampleTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/PathDirectiveExampleTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/WebsocketCoreExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/WebsocketCoreExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/WebsocketCoreExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/WebsocketCoreExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/WebsocketRoutingExample.java b/akka-docs/rst/java/code/docs/http/javadsl/server/WebsocketRoutingExample.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/WebsocketRoutingExample.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/WebsocketRoutingExample.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/testkit/MyAppService.java b/akka-docs/rst/java/code/docs/http/javadsl/server/testkit/MyAppService.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/testkit/MyAppService.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/testkit/MyAppService.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/testkit/TestkitExampleTest.java b/akka-docs/rst/java/code/docs/http/javadsl/server/testkit/TestkitExampleTest.java similarity index 100% rename from akka-docs-dev/rst/java/code/docs/http/javadsl/server/testkit/TestkitExampleTest.java rename to akka-docs/rst/java/code/docs/http/javadsl/server/testkit/TestkitExampleTest.java diff --git a/akka-docs/rst/java/code/docs/stream/ActorPublisherDocTest.java b/akka-docs/rst/java/code/docs/stream/ActorPublisherDocTest.java new file mode 100644 index 0000000000..d8206e2323 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/ActorPublisherDocTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.japi.pf.ReceiveBuilder; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.actor.AbstractActorPublisher; +import akka.stream.actor.ActorPublisherMessage; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class ActorPublisherDocTest { + + static ActorSystem system; + + + @BeforeClass + public static void setup() { + system = ActorSystem.create("ActorPublisherDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + //#job-manager + public static class JobManagerProtocol { + final public static class Job { + public final String payload; + + public Job(String payload) { + this.payload = payload; + } + + } + + public static class JobAcceptedMessage { + @Override + public String toString() { + return "JobAccepted"; + } + } + public static final JobAcceptedMessage JobAccepted = new JobAcceptedMessage(); + + public static class JobDeniedMessage { + @Override + public String toString() { + return "JobDenied"; + } + } + public static final JobDeniedMessage JobDenied = new JobDeniedMessage(); + } + public static class JobManager extends AbstractActorPublisher { + + public static Props props() { return Props.create(JobManager.class); } + + private final int MAX_BUFFER_SIZE = 100; + private final List buf = new ArrayList<>(); + + public JobManager() { + receive(ReceiveBuilder. + match(JobManagerProtocol.Job.class, job -> buf.size() == MAX_BUFFER_SIZE, job -> { + sender().tell(JobManagerProtocol.JobDenied, self()); + }). + match(JobManagerProtocol.Job.class, job -> { + sender().tell(JobManagerProtocol.JobAccepted, self()); + + if (buf.isEmpty() && totalDemand() > 0) + onNext(job); + else { + buf.add(job); + deliverBuf(); + } + }). + match(ActorPublisherMessage.Request.class, request -> deliverBuf()). + match(ActorPublisherMessage.Cancel.class, cancel -> context().stop(self())). + build()); + } + + void deliverBuf() { + while (totalDemand() > 0) { + /* + * totalDemand is a Long and could be larger than + * what buf.splitAt can accept + */ + if (totalDemand() <= Integer.MAX_VALUE) { + final List took = + buf.subList(0, Math.min(buf.size(), (int) totalDemand())); + took.forEach(this::onNext); + buf.removeAll(took); + break; + } else { + final List took = + buf.subList(0, Math.min(buf.size(), Integer.MAX_VALUE)); + took.forEach(this::onNext); + buf.removeAll(took); + } + } + } + } + //#job-manager + + @Test + public void demonstrateActorPublisherUsage() { + new JavaTestKit(system) { + private final SilenceSystemOut.System System = SilenceSystemOut.get(getTestActor()); + + { + //#actor-publisher-usage + final Source jobManagerSource = + Source.actorPublisher(JobManager.props()); + + final ActorRef ref = jobManagerSource + .map(job -> job.payload.toUpperCase()) + .map(elem -> { + System.out.println(elem); + return elem; + }) + .to(Sink.ignore()) + .run(mat); + + ref.tell(new JobManagerProtocol.Job("a"), ActorRef.noSender()); + ref.tell(new JobManagerProtocol.Job("b"), ActorRef.noSender()); + ref.tell(new JobManagerProtocol.Job("c"), ActorRef.noSender()); + //#actor-publisher-usage + + expectMsgEquals("A"); + expectMsgEquals("B"); + expectMsgEquals("C"); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/ActorSubscriberDocTest.java b/akka-docs/rst/java/code/docs/stream/ActorSubscriberDocTest.java new file mode 100644 index 0000000000..bc6d44be1d --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/ActorSubscriberDocTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ + +package docs.stream; + +import akka.actor.AbstractActor; +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.japi.pf.ReceiveBuilder; +import akka.routing.ActorRefRoutee; +import akka.routing.RoundRobinRoutingLogic; +import akka.routing.Routee; +import akka.routing.Router; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.actor.AbstractActorSubscriber; +import akka.stream.actor.ActorSubscriberMessage; +import akka.stream.actor.MaxInFlightRequestStrategy; +import akka.stream.actor.RequestStrategy; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class ActorSubscriberDocTest { + + static ActorSystem system; + + + @BeforeClass + public static void setup() { + system = ActorSystem.create("ActorSubscriberDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + //#worker-pool + public static class WorkerPoolProtocol { + + public static class Msg { + public final int id; + public final ActorRef replyTo; + + public Msg(int id, ActorRef replyTo) { + this.id = id; + this.replyTo = replyTo; + } + + @Override + public String toString() { + return String.format("Msg(%s, %s)", id, replyTo); + } + } + public static Msg msg(int id, ActorRef replyTo) { + return new Msg(id, replyTo); + } + + + public static class Work { + public final int id; + public Work(int id) { this.id = id; } + + @Override + public String toString() { + return String.format("Work(%s)", id); + } + } + public static Work work(int id) { + return new Work(id); + } + + + public static class Reply { + public final int id; + public Reply(int id) { this.id = id; } + + @Override + public String toString() { + return String.format("Reply(%s)", id); + } + } + public static Reply reply(int id) { + return new Reply(id); + } + + + public static class Done { + public final int id; + public Done(int id) { this.id = id; } + + @Override + public String toString() { + return String.format("Done(%s)", id); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Done done = (Done) o; + + if (id != done.id) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return id; + } + } + public static Done done(int id) { + return new Done(id); + } + + } + + public static class WorkerPool extends AbstractActorSubscriber { + + public static Props props() { return Props.create(WorkerPool.class); } + + final int MAX_QUEUE_SIZE = 10; + final Map queue = new HashMap<>(); + + final Router router; + + @Override + public RequestStrategy requestStrategy() { + return new MaxInFlightRequestStrategy(MAX_QUEUE_SIZE) { + @Override + public int inFlightInternally() { + return queue.size(); + } + }; + } + + public WorkerPool() { + final List routees = new ArrayList<>(); + for (int i = 0; i < 3; i++) + routees.add(new ActorRefRoutee(context().actorOf(Props.create(Worker.class)))); + router = new Router(new RoundRobinRoutingLogic(), routees); + + receive(ReceiveBuilder. + match(ActorSubscriberMessage.OnNext.class, on -> on.element() instanceof WorkerPoolProtocol.Msg, + onNext -> { + WorkerPoolProtocol.Msg msg = (WorkerPoolProtocol.Msg) onNext.element(); + queue.put(msg.id, msg.replyTo); + + if (queue.size() > MAX_QUEUE_SIZE) + throw new RuntimeException("queued too many: " + queue.size()); + + router.route(WorkerPoolProtocol.work(msg.id), self()); + }). + match(WorkerPoolProtocol.Reply.class, reply -> { + int id = reply.id; + queue.get(id).tell(WorkerPoolProtocol.done(id), self()); + queue.remove(id); + }). + build()); + } + } + + static class Worker extends AbstractActor { + public Worker() { + receive(ReceiveBuilder. + match(WorkerPoolProtocol.Work.class, work -> { + // ... + sender().tell(WorkerPoolProtocol.reply(work.id), self()); + }).build()); + } + } + //#worker-pool + + @Test + public void demonstrateActorPublisherUsage() { + new JavaTestKit(system) { + + { + final ActorRef replyTo = getTestActor(); + + //#actor-subscriber-usage + final int N = 117; + final List data = new ArrayList<>(N); + for (int i = 0; i < N; i++) { + data.add(i); + } + + Source.from(data) + .map(i -> WorkerPoolProtocol.msg(i, replyTo)) + .runWith(Sink.actorSubscriber(WorkerPool.props()), mat); + //#actor-subscriber-usage + + List got = Arrays.asList(receiveN(N)); + Collections.sort(got, new Comparator() { + @Override + public int compare(Object o1, Object o2) { + if (o1 instanceof WorkerPoolProtocol.Done && o2 instanceof WorkerPoolProtocol.Done) { + return ((WorkerPoolProtocol.Done) o1).id - ((WorkerPoolProtocol.Done) o2).id; + } else return 0; + } + }); + int i = 0; + for (; i < N; i++) { + assertEquals(String.format("Expected %d, but got %s", i, got.get(i)), WorkerPoolProtocol.done(i), got.get(i)); + } + assertEquals(String.format("Expected 117 messages but got %d", i), i, 117); + } + }; + } + + +} diff --git a/akka-docs/rst/java/code/docs/stream/BidiFlowDocTest.java b/akka-docs/rst/java/code/docs/stream/BidiFlowDocTest.java new file mode 100644 index 0000000000..57d4c9cd81 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/BidiFlowDocTest.java @@ -0,0 +1,236 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import akka.stream.javadsl.GraphDSL; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import akka.actor.ActorSystem; +import akka.japi.pf.PFBuilder; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.stage.*; +import akka.testkit.JavaTestKit; +import akka.util.ByteIterator; +import akka.util.ByteString; +import akka.util.ByteStringBuilder; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; +import static org.junit.Assert.assertArrayEquals; + +public class BidiFlowDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + //#codec + static interface Message {} + static class Ping implements Message { + final int id; + public Ping(int id) { this.id = id; } + @Override + public boolean equals(Object o) { + if (o instanceof Ping) { + return ((Ping) o).id == id; + } else return false; + } + @Override + public int hashCode() { + return id; + } + } + static class Pong implements Message { + final int id; + public Pong(int id) { this.id = id; } + @Override + public boolean equals(Object o) { + if (o instanceof Pong) { + return ((Pong) o).id == id; + } else return false; + } + @Override + public int hashCode() { + return id; + } + } + + //#codec-impl + public static ByteString toBytes(Message msg) { + //#implementation-details-elided + if (msg instanceof Ping) { + final int id = ((Ping) msg).id; + return new ByteStringBuilder().putByte((byte) 1) + .putInt(id, ByteOrder.LITTLE_ENDIAN).result(); + } else { + final int id = ((Pong) msg).id; + return new ByteStringBuilder().putByte((byte) 2) + .putInt(id, ByteOrder.LITTLE_ENDIAN).result(); + } + //#implementation-details-elided + } + + public static Message fromBytes(ByteString bytes) { + //#implementation-details-elided + final ByteIterator it = bytes.iterator(); + switch(it.getByte()) { + case 1: + return new Ping(it.getInt(ByteOrder.LITTLE_ENDIAN)); + case 2: + return new Pong(it.getInt(ByteOrder.LITTLE_ENDIAN)); + default: + throw new RuntimeException("message format error"); + } + //#implementation-details-elided + } + //#codec-impl + + //#codec + @SuppressWarnings("unused") + //#codec + public final BidiFlow codecVerbose = + BidiFlow.fromGraph(GraphDSL.create(b -> { + final FlowShape top = + b.add(Flow.of(Message.class).map(BidiFlowDocTest::toBytes)); + final FlowShape bottom = + b.add(Flow.of(ByteString.class).map(BidiFlowDocTest::fromBytes)); + return BidiShape.fromFlows(top, bottom); + })); + + public final BidiFlow codec = + BidiFlow.fromFunctions(BidiFlowDocTest::toBytes, BidiFlowDocTest::fromBytes); + //#codec + + //#framing + public static ByteString addLengthHeader(ByteString bytes) { + final int len = bytes.size(); + return new ByteStringBuilder() + .putInt(len, ByteOrder.LITTLE_ENDIAN) + .append(bytes) + .result(); + } + + public static class FrameParser extends PushPullStage { + // this holds the received but not yet parsed bytes + private ByteString stash = ByteString.empty(); + // this holds the current message length or -1 if at a boundary + private int needed = -1; + + @Override + public SyncDirective onPull(Context ctx) { + return run(ctx); + } + + @Override + public SyncDirective onPush(ByteString bytes, Context ctx) { + stash = stash.concat(bytes); + return run(ctx); + } + + @Override + public TerminationDirective onUpstreamFinish(Context ctx) { + if (stash.isEmpty()) return ctx.finish(); + else return ctx.absorbTermination(); // we still have bytes to emit + } + + private SyncDirective run(Context ctx) { + if (needed == -1) { + // are we at a boundary? then figure out next length + if (stash.size() < 4) return pullOrFinish(ctx); + else { + needed = stash.iterator().getInt(ByteOrder.LITTLE_ENDIAN); + stash = stash.drop(4); + return run(ctx); // cycle back to possibly already emit the next chunk + } + } else if (stash.size() < needed) { + // we are in the middle of a message, need more bytes + return pullOrFinish(ctx); + } else { + // we have enough to emit at least one message, so do it + final ByteString emit = stash.take(needed); + stash = stash.drop(needed); + needed = -1; + return ctx.push(emit); + } + } + + /* + * After having called absorbTermination() we cannot pull any more, so if we need + * more data we will just have to give up. + */ + private SyncDirective pullOrFinish(Context ctx) { + if (ctx.isFinishing()) return ctx.finish(); + else return ctx.pull(); + } + } + + public final BidiFlow framing = + BidiFlow.fromGraph(GraphDSL.create(b -> { + final FlowShape top = + b.add(Flow.of(ByteString.class).map(BidiFlowDocTest::addLengthHeader)); + final FlowShape bottom = + b.add(Flow.of(ByteString.class).transform(() -> new FrameParser())); + return BidiShape.fromFlows(top, bottom); + })); + //#framing + + @Test + public void mustCompose() throws Exception { + //#compose + /* construct protocol stack + * +------------------------------------+ + * | stack | + * | | + * | +-------+ +---------+ | + * ~> O~~o | ~> | o~~O ~> + * Message | | codec | ByteString | framing | | ByteString + * <~ O~~o | <~ | o~~O <~ + * | +-------+ +---------+ | + * +------------------------------------+ + */ + final BidiFlow stack = + codec.atop(framing); + + // test it by plugging it into its own inverse and closing the right end + final Flow pingpong = + Flow.of(Message.class).collect(new PFBuilder() + .match(Ping.class, p -> new Pong(p.id)) + .build() + ); + final Flow flow = + stack.atop(stack.reversed()).join(pingpong); + final Future> result = Source + .from(Arrays.asList(0, 1, 2)) + . map(id -> new Ping(id)) + .via(flow) + .grouped(10) + .runWith(Sink.> head(), mat); + final FiniteDuration oneSec = Duration.create(1, TimeUnit.SECONDS); + assertArrayEquals( + new Message[] { new Pong(0), new Pong(1), new Pong(2) }, + Await.result(result, oneSec).toArray(new Message[0])); + //#compose + } +} diff --git a/akka-docs/rst/java/code/docs/stream/CompositionDocTest.java b/akka-docs/rst/java/code/docs/stream/CompositionDocTest.java new file mode 100644 index 0000000000..ec45cfe451 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/CompositionDocTest.java @@ -0,0 +1,308 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import java.util.Arrays; + +import akka.stream.ClosedShape; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import akka.actor.ActorSystem; +import akka.dispatch.Mapper; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.javadsl.Tcp.OutgoingConnection; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import scala.concurrent.*; +import scala.runtime.BoxedUnit; +import scala.Option; + +public class CompositionDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void nonNestedFlow() throws Exception { + //#non-nested-flow + Source.single(0) + .map(i -> i + 1) + .filter(i -> i != 0) + .map(i -> i - 2) + .to(Sink.fold(0, (acc, i) -> acc + i)); + + // ... where is the nesting? + //#non-nested-flow + } + + @Test + public void nestedFlow() throws Exception { + //#nested-flow + final Source nestedSource = + Source.single(0) // An atomic source + .map(i -> i + 1) // an atomic processing stage + .named("nestedSource"); // wraps up the current Source and gives it a name + + final Flow nestedFlow = + Flow.of(Integer.class).filter(i -> i != 0) // an atomic processing stage + .map(i -> i - 2) // another atomic processing stage + .named("nestedFlow"); // wraps up the Flow, and gives it a name + + final Sink nestedSink = + nestedFlow.to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow + .named("nestedSink"); // wrap it up + + // Create a RunnableGraph + final RunnableGraph runnableGraph = nestedSource.to(nestedSink); + //#nested-flow + } + + @Test + public void reusingComponents() throws Exception { + final Source nestedSource = + Source.single(0) // An atomic source + .map(i -> i + 1) // an atomic processing stage + .named("nestedSource"); // wraps up the current Source and gives it a name + + final Flow nestedFlow = + Flow.of(Integer.class).filter(i -> i != 0) // an atomic processing stage + .map(i -> i - 2) // another atomic processing stage + .named("nestedFlow"); // wraps up the Flow, and gives it a name + + final Sink nestedSink = + nestedFlow.to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow + .named("nestedSink"); // wrap it up + + //#reuse + // Create a RunnableGraph from our components + final RunnableGraph runnableGraph = nestedSource.to(nestedSink); + + // Usage is uniform, no matter if modules are composite or atomic + final RunnableGraph runnableGraph2 = + Source.single(0).to(Sink.fold(0, (acc, i) -> acc + i)); + //#reuse + } + + @Test + public void complexGraph() throws Exception { + //#complex-graph + RunnableGraph.fromGraph( + GraphDSL.create(builder -> { + final Outlet A = builder.add(Source.single(0)).out(); + final UniformFanOutShape B = builder.add(Broadcast.create(2)); + final UniformFanInShape C = builder.add(Merge.create(2)); + final FlowShape D = + builder.add(Flow.of(Integer.class).map(i -> i + 1)); + final UniformFanOutShape E = builder.add(Balance.create(2)); + final UniformFanInShape F = builder.add(Merge.create(2)); + final Inlet G = builder.add(Sink. foreach(System.out::println)).in(); + + builder.from(F).toFanIn(C); + builder.from(A).viaFanOut(B).viaFanIn(C).toFanIn(F); + builder.from(B).via(D).viaFanOut(E).toFanIn(F); + builder.from(E).toInlet(G); + return ClosedShape.getInstance(); + })); + //#complex-graph + + //#complex-graph-alt + RunnableGraph.fromGraph( + GraphDSL.create(builder -> { + final SourceShape A = builder.add(Source.single(0)); + final UniformFanOutShape B = builder.add(Broadcast.create(2)); + final UniformFanInShape C = builder.add(Merge.create(2)); + final FlowShape D = + builder.add(Flow.of(Integer.class).map(i -> i + 1)); + final UniformFanOutShape E = builder.add(Balance.create(2)); + final UniformFanInShape F = builder.add(Merge.create(2)); + final SinkShape G = builder.add(Sink.foreach(System.out::println)); + + builder.from(F.out()).toInlet(C.in(0)); + builder.from(A).toInlet(B.in()); + builder.from(B.out(0)).toInlet(C.in(1)); + builder.from(C.out()).toInlet(F.in(0)); + builder.from(B.out(1)).via(D).toInlet(E.in()); + builder.from(E.out(0)).toInlet(F.in(1)); + builder.from(E.out(1)).to(G); + return ClosedShape.getInstance(); + })); + //#complex-graph-alt + } + + @Test + public void partialGraph() throws Exception { + //#partial-graph + final Graph, BoxedUnit> partial = + GraphDSL.create(builder -> { + final UniformFanOutShape B = builder.add(Broadcast.create(2)); + final UniformFanInShape C = builder.add(Merge.create(2)); + final UniformFanOutShape E = builder.add(Balance.create(2)); + final UniformFanInShape F = builder.add(Merge.create(2)); + + builder.from(F.out()).toInlet(C.in(0)); + builder.from(B).viaFanIn(C).toFanIn(F); + builder.from(B).via(builder.add(Flow.of(Integer.class).map(i -> i + 1))).viaFanOut(E).toFanIn(F); + + return new FlowShape(B.in(), E.out(1)); + }); + + //#partial-graph + + //#partial-use + Source.single(0).via(partial).to(Sink.ignore()); + //#partial-use + + //#partial-flow-dsl + // Convert the partial graph of FlowShape to a Flow to get + // access to the fluid DSL (for example to be able to call .filter()) + final Flow flow = Flow.fromGraph(partial); + + // Simple way to create a graph backed Source + final Source source = Source.fromGraph( + GraphDSL.create(builder -> { + final UniformFanInShape merge = builder.add(Merge.create(2)); + builder.from(builder.add(Source.single(0))).toFanIn(merge); + builder.from(builder.add(Source.from(Arrays.asList(2, 3, 4)))).toFanIn(merge); + // Exposing exactly one output port + return new SourceShape(merge.out()); + }) + ); + + // Building a Sink with a nested Flow, using the fluid DSL + final Sink sink = Flow.of(Integer.class) + .map(i -> i * 2) + .drop(10) + .named("nestedFlow") + .to(Sink.head()); + + // Putting all together + final RunnableGraph closed = source.via(flow.filter(i -> i > 1)).to(sink); + //#partial-flow-dsl + } + + @Test + public void closedGraph() throws Exception { + //#embed-closed + final RunnableGraph closed1 = + Source.single(0).to(Sink.foreach(System.out::println)); + final RunnableGraph closed2 = + RunnableGraph.fromGraph( + GraphDSL.create(builder -> { + final ClosedShape embeddedClosed = builder.add(closed1); + return embeddedClosed; // Could return ClosedShape.getInstance() + })); + //#embed-closed + } + + //#mat-combine-4a + static class MyClass { + private Promise> p; + private OutgoingConnection conn; + + public MyClass(Promise> p, OutgoingConnection conn) { + this.p = p; + this.conn = conn; + } + + public void close() { + p.success(Option.empty()); + } + } + + static class Combiner { + static Future f(Promise> p, + Pair, Future> rest) { + return rest.first().map(new Mapper() { + public MyClass apply(OutgoingConnection c) { + return new MyClass(p, c); + } + }, system.dispatcher()); + } + } + //#mat-combine-4a + + @Test + public void materializedValues() throws Exception { + //#mat-combine-1 + // Materializes to Promise (red) + final Source>> source = Source.maybe(); + + // Materializes to BoxedUnit (black) + final Flow flow1 = Flow.of(Integer.class).take(100); + + // Materializes to Promise> (red) + final Source>> nestedSource = + source.viaMat(flow1, Keep.left()).named("nestedSource"); + //#mat-combine-1 + + //#mat-combine-2 + // Materializes to BoxedUnit (orange) + final Flow flow2 = Flow.of(Integer.class) + .map(i -> ByteString.fromString(i.toString())); + + // Materializes to Future (yellow) + final Flow> flow3 = + Tcp.get(system).outgoingConnection("localhost", 8080); + + // Materializes to Future (yellow) + final Flow> nestedFlow = + flow2.viaMat(flow3, Keep.right()).named("nestedFlow"); + //#mat-combine-2 + + //#mat-combine-3 + // Materializes to Future (green) + final Sink> sink = Sink + .fold("", (acc, i) -> acc + i.utf8String()); + + // Materializes to Pair, Future> (blue) + final Sink, Future>> nestedSink = + nestedFlow.toMat(sink, Keep.both()); + //#mat-combine-3 + + //#mat-combine-4b + // Materializes to Future (purple) + final RunnableGraph> runnableGraph = + nestedSource.toMat(nestedSink, Combiner::f); + //#mat-combine-4b + } + + @Test + public void attributes() throws Exception { + //#attributes-inheritance + final Source nestedSource = + Source.single(0) + .map(i -> i + 1) + .named("nestedSource"); // Wrap, no inputBuffer set + + final Flow nestedFlow = + Flow.of(Integer.class).filter(i -> i != 0) + .via(Flow.of(Integer.class) + .map(i -> i - 2) + .withAttributes(Attributes.inputBuffer(4, 4))) // override + .named("nestedFlow"); // Wrap, no inputBuffer set + + final Sink nestedSink = + nestedFlow.to(Sink.fold(0, (acc, i) -> acc + i)) // wire an atomic sink to the nestedFlow + .withAttributes(Attributes.name("nestedSink") + .and(Attributes.inputBuffer(3, 3))); // override + //#attributes-inheritance + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/FlowDocTest.java b/akka-docs/rst/java/code/docs/stream/FlowDocTest.java new file mode 100644 index 0000000000..8d486cdfe0 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/FlowDocTest.java @@ -0,0 +1,301 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import akka.japi.Pair; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.Promise; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; +import scala.Option; +import akka.actor.ActorSystem; +import akka.actor.Cancellable; +import akka.dispatch.Futures; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; + +public class FlowDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void sourceIsImmutable() throws Exception { + //#source-immutable + final Source source = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + source.map(x -> 0); // has no effect on source, since it's immutable + source.runWith(Sink.fold(0, (agg, next) -> agg + next), mat); // 55 + + // returns new Source, with `map()` appended + final Source zeroes = source.map(x -> 0); + final Sink> fold = + Sink.fold(0, (agg, next) -> agg + next); + zeroes.runWith(fold, mat); // 0 + //#source-immutable + + int result = Await.result( + zeroes.runWith(fold, mat), + Duration.create(3, TimeUnit.SECONDS) + ); + assertEquals(0, result); + } + + @Test + public void materializationInSteps() throws Exception { + //#materialization-in-steps + final Source source = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + // note that the Future is scala.concurrent.Future + final Sink> sink = + Sink.fold(0, (aggr, next) -> aggr + next); + + // connect the Source to the Sink, obtaining a RunnableFlow + final RunnableGraph> runnable = + source.toMat(sink, Keep.right()); + + // materialize the flow + final Future sum = runnable.run(mat); + //#materialization-in-steps + + int result = Await.result(sum, Duration.create(3, TimeUnit.SECONDS)); + assertEquals(55, result); + } + + @Test + public void materializationRunWith() throws Exception { + //#materialization-runWith + final Source source = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + final Sink> sink = + Sink.fold(0, (aggr, next) -> aggr + next); + + // materialize the flow, getting the Sinks materialized value + final Future sum = source.runWith(sink, mat); + //#materialization-runWith + + int result = Await.result(sum, Duration.create(3, TimeUnit.SECONDS)); + assertEquals(55, result); + } + + @Test + public void materializedMapUnique() throws Exception { + //#stream-reuse + // connect the Source to the Sink, obtaining a RunnableGraph + final Sink> sink = + Sink.fold(0, (aggr, next) -> aggr + next); + final RunnableGraph> runnable = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)).toMat(sink, Keep.right()); + + // get the materialized value of the FoldSink + final Future sum1 = runnable.run(mat); + final Future sum2 = runnable.run(mat); + + // sum1 and sum2 are different Futures! + //#stream-reuse + + int result1 = Await.result(sum1, Duration.create(3, TimeUnit.SECONDS)); + assertEquals(55, result1); + int result2 = Await.result(sum2, Duration.create(3, TimeUnit.SECONDS)); + assertEquals(55, result2); + } + + @Test + @SuppressWarnings("unused") + public void compoundSourceCannotBeUsedAsKey() throws Exception { + //#compound-source-is-not-keyed-runWith + final Object tick = new Object(); + + final FiniteDuration oneSecond = Duration.create(1, TimeUnit.SECONDS); + //akka.actor.Cancellable + final Source timer = + Source.tick(oneSecond, oneSecond, tick); + + Sink.ignore().runWith(timer, mat); + + final Source timerMap = timer.map(t -> "tick"); + // WRONG: returned type is not the timers Cancellable! + // Cancellable timerCancellable = Sink.ignore().runWith(timerMap, mat); + //#compound-source-is-not-keyed-runWith + + //#compound-source-is-not-keyed-run + // retain the materialized map, in order to retrieve the timer's Cancellable + final Cancellable timerCancellable = timer.to(Sink.ignore()).run(mat); + timerCancellable.cancel(); + //#compound-source-is-not-keyed-run + } + + @Test + public void creatingSourcesSinks() throws Exception { + //#source-sink + // Create a source from an Iterable + List list = new LinkedList(); + list.add(1); + list.add(2); + list.add(3); + Source.from(list); + + // Create a source form a Future + Source.fromFuture(Futures.successful("Hello Streams!")); + + // Create a source from a single element + Source.single("only one element"); + + // an empty source + Source.empty(); + + // Sink that folds over the stream and returns a Future + // of the final result in the MaterializedMap + Sink.fold(0, (Integer aggr, Integer next) -> aggr + next); + + // Sink that returns a Future in the MaterializedMap, + // containing the first element of the stream + Sink.head(); + + // A Sink that consumes a stream without doing anything with the elements + Sink.ignore(); + + // A Sink that executes a side-effecting call for every element of the stream + Sink.foreach(System.out::println); + //#source-sink + } + + @Test + public void variousWaysOfConnecting() throws Exception { + //#flow-connecting + // Explicitly creating and wiring up a Source, Sink and Flow + Source.from(Arrays.asList(1, 2, 3, 4)) + .via(Flow.of(Integer.class).map(elem -> elem * 2)) + .to(Sink.foreach(System.out::println)); + + // Starting from a Source + final Source source = Source.from(Arrays.asList(1, 2, 3, 4)) + .map(elem -> elem * 2); + source.to(Sink.foreach(System.out::println)); + + // Starting from a Sink + final Sink sink = Flow.of(Integer.class) + .map(elem -> elem * 2).to(Sink.foreach(System.out::println)); + Source.from(Arrays.asList(1, 2, 3, 4)).to(sink); + //#flow-connecting + } + + @Test + public void transformingMaterialized() throws Exception { + + FiniteDuration oneSecond = FiniteDuration.apply(1, TimeUnit.SECONDS); + Flow throttler = + Flow.fromGraph(GraphDSL.create( + Source.tick(oneSecond, oneSecond, ""), + (b, tickSource) -> { + FanInShape2 zip = b.add(ZipWith.create(Keep.right())); + b.from(tickSource).toInlet(zip.in0()); + return FlowShape.of(zip.in1(), zip.out()); + })); + + //#flow-mat-combine + + // An empty source that can be shut down explicitly from the outside + Source>> source = Source.maybe(); + + // A flow that internally throttles elements to 1/second, and returns a Cancellable + // which can be used to shut down the stream + Flow flow = throttler; + + // A sink that returns the first element of a stream in the returned Future + Sink> sink = Sink.head(); + + + // By default, the materialized value of the leftmost stage is preserved + RunnableGraph>> r1 = source.via(flow).to(sink); + + // Simple selection of materialized values by using Keep.right + RunnableGraph r2 = source.viaMat(flow, Keep.right()).to(sink); + RunnableGraph> r3 = source.via(flow).toMat(sink, Keep.right()); + + // Using runWith will always give the materialized values of the stages added + // by runWith() itself + Future r4 = source.via(flow).runWith(sink, mat); + Promise> r5 = flow.to(sink).runWith(source, mat); + Pair>, Future> r6 = flow.runWith(source, sink, mat); + + // Using more complext combinations + RunnableGraph>, Cancellable>> r7 = + source.viaMat(flow, Keep.both()).to(sink); + + RunnableGraph>, Future>> r8 = + source.via(flow).toMat(sink, Keep.both()); + + RunnableGraph>, Cancellable>, Future>> r9 = + source.viaMat(flow, Keep.both()).toMat(sink, Keep.both()); + + RunnableGraph>> r10 = + source.viaMat(flow, Keep.right()).toMat(sink, Keep.both()); + + // It is also possible to map over the materialized values. In r9 we had a + // doubly nested pair, but we want to flatten it out + + + RunnableGraph r11 = + r9.mapMaterializedValue( (nestedTuple) -> { + Promise> p = nestedTuple.first().first(); + Cancellable c = nestedTuple.first().second(); + Future f = nestedTuple.second(); + + // Picking the Cancellable, but we could also construct a domain class here + return c; + }); + //#flow-mat-combine + } + + public void fusingAndAsync() { + //#explicit-fusing + Flow flow = + Flow.of(Integer.class).map(x -> x * 2).filter(x -> x > 500); + Graph, BoxedUnit> fused = + akka.stream.Fusing.aggressive(flow); + + Source.fromIterator(() -> Stream.iterate(0, x -> x + 1).iterator()) + .via(fused) + .take(1000); + //#explicit-fusing + + //#flow-async + Source.range(1, 3) + .map(x -> x + 1) + .withAttributes(Attributes.asyncBoundary()) + .map(x -> x * 2) + .to(Sink.ignore()); + //#flow-async + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/FlowErrorDocTest.java b/akka-docs/rst/java/code/docs/stream/FlowErrorDocTest.java new file mode 100644 index 0000000000..608ae96eef --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/FlowErrorDocTest.java @@ -0,0 +1,140 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import static org.junit.Assert.assertEquals; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.ActorMaterializerSettings; +import akka.stream.Materializer; +import akka.stream.Supervision; +import akka.stream.javadsl.Flow; +import akka.stream.ActorAttributes; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.japi.function.Function; +import akka.testkit.JavaTestKit; + +public class FlowErrorDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + @Test(expected = ArithmeticException.class) + public void demonstrateFailStream() throws Exception { + //#stop + final Materializer mat = ActorMaterializer.create(system); + final Source source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5)) + .map(elem -> 100 / elem); + final Sink> fold = + Sink.fold(0, (acc, elem) -> acc + elem); + final Future result = source.runWith(fold, mat); + // division by zero will fail the stream and the + // result here will be a Future completed with Failure(ArithmeticException) + //#stop + + Await.result(result, Duration.create(3, TimeUnit.SECONDS)); + } + + @Test + public void demonstrateResumeStream() throws Exception { + //#resume + final Function decider = exc -> { + if (exc instanceof ArithmeticException) + return Supervision.resume(); + else + return Supervision.stop(); + }; + final Materializer mat = ActorMaterializer.create( + ActorMaterializerSettings.create(system).withSupervisionStrategy(decider), + system); + final Source source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5)) + .map(elem -> 100 / elem); + final Sink> fold = + Sink.fold(0, (acc, elem) -> acc + elem); + final Future result = source.runWith(fold, mat); + // the element causing division by zero will be dropped + // result here will be a Future completed with Success(228) + //#resume + + assertEquals(Integer.valueOf(228), Await.result(result, Duration.create(3, TimeUnit.SECONDS))); + } + + @Test + public void demonstrateResumeSectionStream() throws Exception { + //#resume-section + final Materializer mat = ActorMaterializer.create(system); + final Function decider = exc -> { + if (exc instanceof ArithmeticException) + return Supervision.resume(); + else + return Supervision.stop(); + }; + final Flow flow = + Flow.of(Integer.class).filter(elem -> 100 / elem < 50).map(elem -> 100 / (5 - elem)) + .withAttributes(ActorAttributes.withSupervisionStrategy(decider)); + final Source source = Source.from(Arrays.asList(0, 1, 2, 3, 4, 5)) + .via(flow); + final Sink> fold = + Sink.fold(0, (acc, elem) -> acc + elem); + final Future result = source.runWith(fold, mat); + // the elements causing division by zero will be dropped + // result here will be a Future completed with Success(150) + //#resume-section + + assertEquals(Integer.valueOf(150), Await.result(result, Duration.create(3, TimeUnit.SECONDS))); + } + + @Test + public void demonstrateRestartSectionStream() throws Exception { + //#restart-section + final Materializer mat = ActorMaterializer.create(system); + final Function decider = exc -> { + if (exc instanceof IllegalArgumentException) + return Supervision.restart(); + else + return Supervision.stop(); + }; + final Flow flow = + Flow.of(Integer.class).scan(0, (acc, elem) -> { + if (elem < 0) throw new IllegalArgumentException("negative not allowed"); + else return acc + elem; + }) + .withAttributes(ActorAttributes.withSupervisionStrategy(decider)); + final Source source = Source.from(Arrays.asList(1, 3, -1, 5, 7)) + .via(flow); + final Future> result = source.grouped(1000) + .runWith(Sink.>head(), mat); + // the negative element cause the scan stage to be restarted, + // i.e. start from 0 again + // result here will be a Future completed with Success(List(0, 1, 4, 0, 5, 12)) + //#restart-section + + assertEquals( + Arrays.asList(0, 1, 4, 0, 5, 12), + Await.result(result, Duration.create(3, TimeUnit.SECONDS))); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/FlowGraphDocTest.java b/akka-docs/rst/java/code/docs/stream/FlowGraphDocTest.java new file mode 100644 index 0000000000..d46e0840c8 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/FlowGraphDocTest.java @@ -0,0 +1,172 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import akka.stream.ClosedShape; +import akka.stream.SourceShape; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; + +public class FlowGraphDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowGraphDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void demonstrateBuildSimpleGraph() throws Exception { + //#simple-flow-graph + final Source in = Source.from(Arrays.asList(1, 2, 3, 4, 5)); + final Sink, Future>> sink = Sink.head(); + final Sink, Future>> sink2 = Sink.head(); + final Flow f1 = Flow.of(Integer.class).map(elem -> elem + 10); + final Flow f2 = Flow.of(Integer.class).map(elem -> elem + 20); + final Flow f3 = Flow.of(Integer.class).map(elem -> elem.toString()); + final Flow f4 = Flow.of(Integer.class).map(elem -> elem + 30); + + final RunnableGraph>> result = + RunnableGraph.>>fromGraph( + GraphDSL + .create( + sink, + (builder, out) -> { + final UniformFanOutShape bcast = builder.add(Broadcast.create(2)); + final UniformFanInShape merge = builder.add(Merge.create(2)); + + final Outlet source = builder.add(in).out(); + builder.from(source).via(builder.add(f1)) + .viaFanOut(bcast).via(builder.add(f2)).viaFanIn(merge) + .via(builder.add(f3.grouped(1000))).to(out); + builder.from(bcast).via(builder.add(f4)).toFanIn(merge); + return ClosedShape.getInstance(); + })); + //#simple-flow-graph + final List list = Await.result(result.run(mat), Duration.create(3, TimeUnit.SECONDS)); + final String[] res = list.toArray(new String[] {}); + Arrays.sort(res, null); + assertArrayEquals(new String[] { "31", "32", "33", "34", "35", "41", "42", "43", "44", "45" }, res); + } + + @Test + @SuppressWarnings("unused") + public void demonstrateConnectErrors() { + try { + //#simple-graph + final RunnableGraph g = + RunnableGraph.fromGraph( + GraphDSL + .create((b) -> { + final SourceShape source1 = b.add(Source.from(Arrays.asList(1, 2, 3, 4, 5))); + final SourceShape source2 = b.add(Source.from(Arrays.asList(1, 2, 3, 4, 5))); + final FanInShape2> zip = b.add(Zip.create()); + b.from(source1).toInlet(zip.in0()); + b.from(source2).toInlet(zip.in1()); + return ClosedShape.getInstance(); + } + ) + ); + // unconnected zip.out (!) => "The inlets [] and outlets [] must correspond to the inlets [] and outlets [ZipWith2.out]" + //#simple-graph + fail("expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + assertTrue(e != null && e.getMessage() != null && e.getMessage().contains("must correspond to")); + } + } + + @Test + public void demonstrateReusingFlowInGraph() throws Exception { + //#flow-graph-reusing-a-flow + final Sink> topHeadSink = Sink.head(); + final Sink> bottomHeadSink = Sink.head(); + final Flow sharedDoubler = Flow.of(Integer.class).map(elem -> elem * 2); + + final RunnableGraph, Future>> g = + RunnableGraph., Future>>fromGraph( + GraphDSL.create( + topHeadSink, // import this sink into the graph + bottomHeadSink, // and this as well + Keep.both(), + (b, top, bottom) -> { + final UniformFanOutShape bcast = + b.add(Broadcast.create(2)); + + b.from(b.add(Source.single(1))).viaFanOut(bcast) + .via(b.add(sharedDoubler)).to(top); + b.from(bcast).via(b.add(sharedDoubler)).to(bottom); + return ClosedShape.getInstance(); + } + ) + ); + //#flow-graph-reusing-a-flow + final Pair, Future> pair = g.run(mat); + assertEquals(Integer.valueOf(2), Await.result(pair.first(), Duration.create(3, TimeUnit.SECONDS))); + assertEquals(Integer.valueOf(2), Await.result(pair.second(), Duration.create(3, TimeUnit.SECONDS))); + } + + @Test + public void demonstrateMatValue() throws Exception { + //#flow-graph-matvalue + final Sink> foldSink = Sink. fold(0, (a, b) -> { + return a + b; + }); + + final Flow, Integer, BoxedUnit> flatten = Flow.>create() + .mapAsync(4, x -> { + return x; + }); + + final Flow> foldingFlow = Flow.fromGraph( + GraphDSL.create(foldSink, + (b, fold) -> { + return FlowShape.of( + fold.in(), + b.from(b.materializedValue()).via(b.add(flatten)).out()); + })); + //#flow-graph-matvalue + + //#flow-graph-matvalue-cycle + // This cannot produce any value: + final Source> cyclicSource = Source.fromGraph( + GraphDSL.create(foldSink, + (b, fold) -> { + // - Fold cannot complete until its upstream mapAsync completes + // - mapAsync cannot complete until the materialized Future produced by + // fold completes + // As a result this Source will never emit anything, and its materialited + // Future will never complete + b.from(b.materializedValue()).via(b.add(flatten)).to(fold); + return SourceShape.of(b.from(b.materializedValue()).via(b.add(flatten)).out()); + })); + + //#flow-graph-matvalue-cycle + } +} diff --git a/akka-docs/rst/java/code/docs/stream/FlowParallelismDocTest.java b/akka-docs/rst/java/code/docs/stream/FlowParallelismDocTest.java new file mode 100644 index 0000000000..2570f920de --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/FlowParallelismDocTest.java @@ -0,0 +1,146 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream; + +import scala.runtime.BoxedUnit; + +import static org.junit.Assert.assertEquals; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import akka.actor.ActorSystem; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; + +public class FlowParallelismDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + static class ScoopOfBatter {} + static class HalfCookedPancake {} + static class Pancake {} + + //#pipelining + Flow fryingPan1 = + Flow.of(ScoopOfBatter.class).map(batter -> new HalfCookedPancake()); + + Flow fryingPan2 = + Flow.of(HalfCookedPancake.class).map(halfCooked -> new Pancake()); + //#pipelining + + @Test + public void demonstratePipelining() { + //#pipelining + + // With the two frying pans we can fully cook pancakes + Flow pancakeChef = fryingPan1.via(fryingPan2); + //#pipelining + } + + @Test + public void demonstrateParallelism() { + //#parallelism + Flow fryingPan = + Flow.of(ScoopOfBatter.class).map(batter -> new Pancake()); + + Flow pancakeChef = + Flow.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape mergePancakes = + b.add(Merge.create(2)); + final UniformFanOutShape dispatchBatter = + b.add(Balance.create(2)); + + // Using two frying pans in parallel, both fully cooking a pancake from the batter. + // We always put the next scoop of batter to the first frying pan that becomes available. + b.from(dispatchBatter.out(0)).via(b.add(fryingPan)).toInlet(mergePancakes.in(0)); + // Notice that we used the "fryingPan" flow without importing it via builder.add(). + // Flows used this way are auto-imported, which in this case means that the two + // uses of "fryingPan" mean actually different stages in the graph. + b.from(dispatchBatter.out(1)).via(b.add(fryingPan)).toInlet(mergePancakes.in(1)); + + return FlowShape.of(dispatchBatter.in(), mergePancakes.out()); + })); + //#parallelism + } + + @Test + public void parallelPipeline() { + //#parallel-pipeline + Flow pancakeChef = + Flow.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape mergePancakes = + b.add(Merge.create(2)); + final UniformFanOutShape dispatchBatter = + b.add(Balance.create(2)); + + // Using two pipelines, having two frying pans each, in total using + // four frying pans + b.from(dispatchBatter.out(0)) + .via(b.add(fryingPan1)) + .via(b.add(fryingPan2)) + .toInlet(mergePancakes.in(0)); + + b.from(dispatchBatter.out(1)) + .via(b.add(fryingPan1)) + .via(b.add(fryingPan2)) + .toInlet(mergePancakes.in(1)); + + return FlowShape.of(dispatchBatter.in(), mergePancakes.out()); + })); + //#parallel-pipeline + } + + @Test + public void pipelinedParallel() { + //#pipelined-parallel + Flow pancakeChefs1 = + Flow.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape mergeHalfCooked = + b.add(Merge.create(2)); + final UniformFanOutShape dispatchBatter = + b.add(Balance.create(2)); + + // Two chefs work with one frying pan for each, half-frying the pancakes then putting + // them into a common pool + b.from(dispatchBatter.out(0)).via(b.add(fryingPan1)).toInlet(mergeHalfCooked.in(0)); + b.from(dispatchBatter.out(1)).via(b.add(fryingPan1)).toInlet(mergeHalfCooked.in(1)); + + return FlowShape.of(dispatchBatter.in(), mergeHalfCooked.out()); + })); + + Flow pancakeChefs2 = + Flow.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape mergePancakes = + b.add(Merge.create(2)); + final UniformFanOutShape dispatchHalfCooked = + b.add(Balance.create(2)); + + // Two chefs work with one frying pan for each, finishing the pancakes then putting + // them into a common pool + b.from(dispatchHalfCooked.out(0)).via(b.add(fryingPan2)).toInlet(mergePancakes.in(0)); + b.from(dispatchHalfCooked.out(1)).via(b.add(fryingPan2)).toInlet(mergePancakes.in(1)); + + return FlowShape.of(dispatchHalfCooked.in(), mergePancakes.out()); + })); + + Flow kitchen = + pancakeChefs1.via(pancakeChefs2); + //#pipelined-parallel + } +} \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/stream/FlowStagesDocTest.java b/akka-docs/rst/java/code/docs/stream/FlowStagesDocTest.java new file mode 100644 index 0000000000..41fac66ccb --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/FlowStagesDocTest.java @@ -0,0 +1,256 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.Predicate; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.stage.*; +import akka.stream.testkit.*; +import akka.stream.testkit.javadsl.*; +import akka.testkit.JavaTestKit; + +public class FlowStagesDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowStagesDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + static //#one-to-one + public class Map extends PushPullStage { + private final Function f; + public Map(Function f) { + this.f = f; + } + + @Override public SyncDirective onPush(A elem, Context ctx) { + return ctx.push(f.apply(elem)); + } + + @Override public SyncDirective onPull(Context ctx) { + return ctx.pull(); + } + } + //#one-to-one + + static //#many-to-one + public class Filter extends PushPullStage { + private final Predicate p; + public Filter(Predicate p) { + this.p = p; + } + + @Override public SyncDirective onPush(A elem, Context ctx) { + if (p.test(elem)) return ctx.push(elem); + else return ctx.pull(); + } + + @Override public SyncDirective onPull(Context ctx) { + return ctx.pull(); + } + } + //#many-to-one + + //#one-to-many + class Duplicator extends PushPullStage { + private A lastElem = null; + private boolean oneLeft = false; + + @Override public SyncDirective onPush(A elem, Context ctx) { + lastElem = elem; + oneLeft = true; + return ctx.push(elem); + } + + @Override public SyncDirective onPull(Context ctx) { + if (!ctx.isFinishing()) { + // the main pulling logic is below as it is demonstrated on the illustration + if (oneLeft) { + oneLeft = false; + return ctx.push(lastElem); + } else + return ctx.pull(); + } else { + // If we need to emit a final element after the upstream + // finished + if (oneLeft) return ctx.pushAndFinish(lastElem); + else return ctx.finish(); + } + } + + @Override public TerminationDirective onUpstreamFinish(Context ctx) { + return ctx.absorbTermination(); + } + + } + //#one-to-many + + static//#pushstage + public class Map2 extends PushStage { + private final Function f; + public Map2(Function f) { + this.f = f; + } + + @Override public SyncDirective onPush(A elem, Context ctx) { + return ctx.push(f.apply(elem)); + } + } + + public class Filter2 extends PushStage { + private final Predicate p; + public Filter2(Predicate p) { + this.p = p; + } + + @Override public SyncDirective onPush(A elem, Context ctx) { + if (p.test(elem)) return ctx.push(elem); + else return ctx.pull(); + } + } + //#pushstage + + static //#doubler-stateful + public class Duplicator2 extends StatefulStage { + @Override public StageState initial() { + return new StageState() { + @Override public SyncDirective onPush(A elem, Context ctx) { + return emit(Arrays.asList(elem, elem).iterator(), ctx); + } + }; + } + } + //#doubler-stateful + + @Test + public void demonstrateVariousPushPullStages() throws Exception { + final Sink>> sink = + Flow.of(Integer.class).grouped(10).toMat(Sink.head(), Keep.right()); + + //#stage-chain + final RunnableGraph>> runnable = + Source + .from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + .transform(() -> new Filter(elem -> elem % 2 == 0)) + .transform(() -> new Duplicator()) + .transform(() -> new Map(elem -> elem / 2)) + .toMat(sink, Keep.right()); + //#stage-chain + + assertEquals(Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5), + Await.result(runnable.run(mat), FiniteDuration.create(3, TimeUnit.SECONDS))); + } + + //#detached + class Buffer2 extends DetachedStage { + final private Integer SIZE = 2; + final private List buf = new ArrayList<>(SIZE); + private Integer capacity = SIZE; + + private boolean isFull() { + return capacity == 0; + } + + private boolean isEmpty() { + return capacity == SIZE; + } + + private T dequeue() { + capacity += 1; + return buf.remove(0); + } + + private void enqueue(T elem) { + capacity -= 1; + buf.add(elem); + } + + public DownstreamDirective onPull(DetachedContext ctx) { + if (isEmpty()) { + if (ctx.isFinishing()) return ctx.finish(); // No more elements will arrive + else return ctx.holdDownstream(); // waiting until new elements + } else { + final T next = dequeue(); + if (ctx.isHoldingUpstream()) return ctx.pushAndPull(next); // release upstream + else return ctx.push(next); + } + } + + public UpstreamDirective onPush(T elem, DetachedContext ctx) { + enqueue(elem); + if (isFull()) return ctx.holdUpstream(); // Queue is now full, wait until new empty slot + else { + if (ctx.isHoldingDownstream()) return ctx.pushAndPull(dequeue()); // Release downstream + else return ctx.pull(); + } + } + + public TerminationDirective onUpstreamFinish(DetachedContext ctx) { + if (!isEmpty()) return ctx.absorbTermination(); // still need to flush from buffer + else return ctx.finish(); // already empty, finishing + } + } + //#detached + + @Test + public void demonstrateDetachedStage() throws Exception { + final Pair,TestSubscriber.Probe> pair = + TestSource.probe(system) + .transform(() -> new Buffer2()) + .toMat(TestSink.probe(system), Keep.both()) + .run(mat); + + final TestPublisher.Probe pub = pair.first(); + final TestSubscriber.Probe sub = pair.second(); + + final FiniteDuration timeout = Duration.create(100, TimeUnit.MILLISECONDS); + + sub.request(2); + sub.expectNoMsg(timeout); + + pub.sendNext(1); + pub.sendNext(2); + sub.expectNext(1, 2); + + pub.sendNext(3); + pub.sendNext(4); + sub.expectNoMsg(timeout); + + sub.request(2); + sub.expectNext(3, 4); + + pub.sendComplete(); + sub.expectComplete(); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/GraphCyclesDocTest.java b/akka-docs/rst/java/code/docs/stream/GraphCyclesDocTest.java new file mode 100644 index 0000000000..2cf443f8d9 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/GraphCyclesDocTest.java @@ -0,0 +1,159 @@ +package docs.stream; + +import java.util.Arrays; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.runtime.BoxedUnit; +import akka.actor.ActorSystem; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.scaladsl.MergePreferred.MergePreferredShape; +import akka.testkit.JavaTestKit; + + +public class GraphCyclesDocTest { + + static ActorSystem system; + + + @BeforeClass + public static void setup() { + system = ActorSystem.create("GraphCyclesDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final static SilenceSystemOut.System System = SilenceSystemOut.get(); + + final Source source = Source.from(Arrays.asList(1, 2, 3, 4, 5)); + + @Test + public void demonstrateDeadlockedCycle() { + //#deadlocked + // WARNING! The graph below deadlocks! + final Flow printFlow = + Flow.of(Integer.class).map(s -> { + System.out.println(s); + return s; + }); + + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape merge = b.add(Merge.create(2)); + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final Outlet src = b.add(source).out(); + final FlowShape printer = b.add(printFlow); + final SinkShape ignore = b.add(Sink.ignore()); + + b.from(src).viaFanIn(merge).via(printer).viaFanOut(bcast).to(ignore); + b.to(merge) .fromFanOut(bcast); + return ClosedShape.getInstance(); + })); + //#deadlocked + } + + @Test + public void demonstrateUnfairCycle() { + final Flow printFlow = + Flow.of(Integer.class).map(s -> { + System.out.println(s); + return s; + }); + //#unfair + // WARNING! The graph below stops consuming from "source" after a few steps + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final MergePreferredShape merge = b.add(MergePreferred.create(1)); + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final Outlet src = b.add(source).out(); + final FlowShape printer = b.add(printFlow); + final SinkShape ignore = b.add(Sink.ignore()); + + b.from(src).viaFanIn(merge).via(printer).viaFanOut(bcast).to(ignore); + b.to(merge.preferred()).fromFanOut(bcast); + return ClosedShape.getInstance(); + })); + //#unfair + } + + @Test + public void demonstrateDroppingCycle() { + final Flow printFlow = + Flow.of(Integer.class).map(s -> { + System.out.println(s); + return s; + }); + //#dropping + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final UniformFanInShape merge = b.add(Merge.create(2)); + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final FlowShape droppyFlow = b.add( + Flow.of(Integer.class).buffer(10, OverflowStrategy.dropHead())); + final Outlet src = b.add(source).out(); + final FlowShape printer = b.add(printFlow); + final SinkShape ignore = b.add(Sink.ignore()); + + b.from(src).viaFanIn(merge).via(printer).viaFanOut(bcast).to(ignore); + b.to(merge).via(droppyFlow).fromFanOut(bcast); + return ClosedShape.getInstance(); + })); + //#dropping + } + + @Test + public void demonstrateZippingCycle() { + final Flow printFlow = + Flow.of(Integer.class).map(s -> { + System.out.println(s); + return s; + }); + //#zipping-dead + // WARNING! The graph below never processes any elements + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final FanInShape2 zip = + b.add(ZipWith.create((Integer left, Integer right) -> left)); + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final FlowShape printer = b.add(printFlow); + final SinkShape ignore = b.add(Sink.ignore()); + + b.from(b.add(source)).toInlet(zip.in0()); + b.from(zip.out()).via(printer).viaFanOut(bcast).to(ignore); + b.to(zip.in1()) .fromFanOut(bcast); + return ClosedShape.getInstance(); + })); + //#zipping-dead + } + + @Test + public void demonstrateLiveZippingCycle() { + final Flow printFlow = + Flow.of(Integer.class).map(s -> { + System.out.println(s); + return s; + }); + //#zipping-live + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final FanInShape2 zip = + b.add(ZipWith.create((Integer left, Integer right) -> left)); + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final UniformFanInShape concat = b.add(Concat.create()); + final FlowShape printer = b.add(printFlow); + final SinkShape ignore = b.add(Sink.ignore()); + + b.from(b.add(source)).toInlet(zip.in0()); + b.from(zip.out()).via(printer).viaFanOut(bcast).to(ignore); + b.to(zip.in1()).viaFanIn(concat).from(b.add(Source.single(1))); + b.to(concat).fromFanOut(bcast); + return ClosedShape.getInstance(); + })); + //#zipping-live + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/GraphStageDocTest.java b/akka-docs/rst/java/code/docs/stream/GraphStageDocTest.java new file mode 100644 index 0000000000..5808a7a881 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/GraphStageDocTest.java @@ -0,0 +1,712 @@ +package docs.stream; + +import akka.actor.ActorSystem; +//#imports +import akka.dispatch.Futures; +import akka.dispatch.Mapper; +import akka.dispatch.OnSuccess; +import akka.japi.Option; +import akka.japi.Predicate; +import akka.japi.function.Effect; +import akka.japi.function.Procedure; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.stage.*; +//#imports +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.testkit.JavaTestKit; +import akka.japi.Function; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import scala.Tuple2; +import scala.concurrent.Await; +import scala.concurrent.ExecutionContext; +import scala.concurrent.Future; +import scala.concurrent.Promise; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class GraphStageDocTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("FlowGraphDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + + //#simple-source + public class NumbersSource extends GraphStage> { + // Define the (sole) output port of this stage + public final Outlet out = Outlet.create("NumbersSource.out"); + + // Define the shape of this stage, which is SourceShape with the port we defined above + private final SourceShape shape = SourceShape.of(out); + @Override + public SourceShape shape() { + return shape; + } + + // This is where the actual (possibly stateful) logic is created + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape()) { + // All state MUST be inside the GraphStageLogic, + // never inside the enclosing GraphStage. + // This state is safe to access and modify from all the + // callbacks that are provided by GraphStageLogic and the + // registered handlers. + private int counter = 1; + + { + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + push(out, counter); + counter += 1; + } + }); + } + + }; + } + + } + //#simple-source + + + @Test + public void demonstrateCustomSourceUsage() throws Exception { + //#simple-source-usage + // A GraphStage is a proper Graph, just like what GraphDSL.create would return + Graph, BoxedUnit> sourceGraph = new NumbersSource(); + + // Create a Source from the Graph to access the DSL + Source mySource = Source.fromGraph(sourceGraph); + + // Returns 55 + Future result1 = mySource.take(10).runFold(0, (sum, next) -> sum + next, mat); + + // The source is reusable. This returns 5050 + Future result2 = mySource.take(100).runFold(0, (sum, next) -> sum + next, mat); + //#simple-source-usage + + assertEquals(Await.result(result1, Duration.create(3, "seconds")), (Integer) 55); + assertEquals(Await.result(result2, Duration.create(3, "seconds")), (Integer) 5050); + } + + + //#one-to-one + public class Map extends GraphStage> { + + private final Function f; + + public Map(Function f) { + this.f = f; + } + + public final Inlet in = Inlet.create("Map.in"); + public final Outlet out = Outlet.create("Map.out"); + + private final FlowShape shape = FlowShape.of(in, out); + @Override + public FlowShape shape() { + return shape; + } + + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + try { + push(out, f.apply(grab(in))); + } catch (Exception ex) { + failStage(ex); + } + } + }); + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + }; + } + + } + //#one-to-one + + @Test + public void demonstrateOneToOne() throws Exception { + // tests: + final Graph, BoxedUnit> stringLength = + Flow.fromGraph(new Map(new Function() { + @Override + public Integer apply(String str) { + return str.length(); + } + })); + + Future result = + Source.from(Arrays.asList("one", "two", "three")) + .via(stringLength) + .runFold(0, (sum, n) -> sum + n, mat); + + assertEquals(new Integer(11), Await.result(result, Duration.create(3, "seconds"))); + } + + //#many-to-one + public final class Filter extends GraphStage> { + + private final Predicate p; + + public Filter(Predicate p) { + this.p = p; + } + + public final Inlet in = Inlet.create("Filter.in"); + public final Outlet out = Outlet.create("Filter.out"); + + private final FlowShape shape = FlowShape.of(in, out); + + @Override + public FlowShape shape() { + return shape; + } + + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + { + + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + if (p.test(elem)) { + push(out, elem); + } else { + pull(in); + } + } + }); + + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + }; + } + } + //#many-to-one + + @Test + public void demonstrateAManyToOneElementGraphStage() throws Exception { + + // tests: + Graph, BoxedUnit> evenFilter = + Flow.fromGraph(new Filter(n -> n % 2 == 0)); + + Future result = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6)) + .via(evenFilter) + .runFold(0, (elem, sum) -> sum + elem, mat); + + assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds"))); + } + + //#one-to-many + public class Duplicator extends GraphStage> { + + public final Inlet in = Inlet.create("Duplicator.in"); + public final Outlet out = Outlet.create("Duplicator.out"); + + private final FlowShape shape = FlowShape.of(in, out); + + @Override + public FlowShape shape() { + return shape; + } + + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + // Again: note that all mutable state + // MUST be inside the GraphStageLogic + Option lastElem = Option.none(); + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + lastElem = Option.some(elem); + push(out, elem); + } + + @Override + public void onUpstreamFinish() { + if (lastElem.isDefined()) { + emit(out, lastElem.get()); + } + complete(out); + } + }); + + + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + if (lastElem.isDefined()) { + push(out, lastElem.get()); + lastElem = Option.none(); + } else { + pull(in); + } + } + }); + } + }; + } + } + //#one-to-many + + @Test + public void demonstrateAOneToManyElementGraphStage() throws Exception { + // tests: + Graph, BoxedUnit> duplicator = + Flow.fromGraph(new Duplicator()); + + Future result = + Source.from(Arrays.asList(1, 2, 3)) + .via(duplicator) + .runFold(0, (n, sum) -> n + sum, mat); + + assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds"))); + + } + + //#simpler-one-to-many + public class Duplicator2 extends GraphStage> { + + public final Inlet in = Inlet.create("Duplicator.in"); + public final Outlet out = Outlet.create("Duplicator.out"); + + private final FlowShape shape = FlowShape.of(in, out); + + @Override + public FlowShape shape() { + return shape; + } + + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + // this will temporarily suspend this handler until the two elems + // are emitted and then reinstates it + emitMultiple(out, Arrays.asList(elem, elem).iterator()); + } + }); + + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + }; + } + } + //#simpler-one-to-many + + + + @Test + public void demonstrateASimplerOneToManyStage() throws Exception { + // tests: + Graph, BoxedUnit> duplicator = + Flow.fromGraph(new Duplicator2()); + + Future result = + Source.from(Arrays.asList(1, 2, 3)) + .via(duplicator) + .runFold(0, (n, sum) -> n + sum, mat); + + assertEquals(new Integer(12), Await.result(result, Duration.create(3, "seconds"))); + } + + @Test + public void demonstrateChainingOfGraphStages() throws Exception { + Graph, Future> sink = Sink.fold("", (acc, n) -> acc + n.toString()); + + //#graph-stage-chain + Future resultFuture = Source.from(Arrays.asList(1,2,3,4,5)) + .via(new Filter((n) -> n % 2 == 0)) + .via(new Duplicator()) + .via(new Map((n) -> n / 2)) + .runWith(sink, mat); + + //#graph-stage-chain + + assertEquals("1122", Await.result(resultFuture, Duration.create(3, "seconds"))); + } + + + //#async-side-channel + // will close upstream when the future completes + public class KillSwitch extends GraphStage> { + + private final Future switchF; + + public KillSwitch(Future switchF) { + this.switchF = switchF; + } + + public final Inlet in = Inlet.create("KillSwitch.in"); + public final Outlet out = Outlet.create("KillSwitch.out"); + + private final FlowShape shape = FlowShape.of(in, out); + @Override + public FlowShape shape() { + return shape; + } + + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + push(out, grab(in)); + } + }); + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + + @Override + public void preStart() { + AsyncCallback callback = createAsyncCallback(new Procedure() { + @Override + public void apply(BoxedUnit param) throws Exception { + completeStage(); + } + }); + + ExecutionContext ec = system.dispatcher(); + switchF.onSuccess(new OnSuccess() { + @Override + public void onSuccess(BoxedUnit result) throws Throwable { + callback.invoke(BoxedUnit.UNIT); + } + }, ec); + } + }; + } + } + //#async-side-channel + + @Test + public void demonstrateAnAsynchronousSideChannel() throws Exception{ + + // tests: + Promise switchF = Futures.promise(); + Graph, BoxedUnit> killSwitch = + Flow.fromGraph(new KillSwitch<>(switchF.future())); + + ExecutionContext ec = system.dispatcher(); + + // TODO this is probably racey, is there a way to make sure it happens after? + Future valueAfterKill = switchF.future().flatMap(new Mapper>() { + @Override + public Future apply(BoxedUnit parameter) { + return Futures.successful(4); + } + }, ec); + + + Future result = + Source.from(Arrays.asList(1, 2, 3)).concat(Source.fromFuture(valueAfterKill)) + .via(killSwitch) + .runFold(0, (n, sum) -> n + sum, mat); + + switchF.success(BoxedUnit.UNIT); + + assertEquals(new Integer(6), Await.result(result, Duration.create(3, "seconds"))); + } + + + //#timed + // each time an event is pushed through it will trigger a period of silence + public class TimedGate extends GraphStage> { + + private final FiniteDuration silencePeriod; + + public TimedGate(FiniteDuration silencePeriod) { + this.silencePeriod = silencePeriod; + } + + public final Inlet in = Inlet.create("TimedGate.in"); + public final Outlet out = Outlet.create("TimedGate.out"); + + private final FlowShape shape = FlowShape.of(in, out); + @Override + public FlowShape shape() { + return shape; + } + + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new TimerGraphStageLogic(shape) { + + private boolean open = false; + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + if (open) pull(in); + else { + push(out, elem); + open = true; + scheduleOnce("key", silencePeriod); + } + } + }); + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + + @Override + public void onTimer(Object key) { + if (key.equals("key")) { + open = false; + } + } + }; + } + } + //#timed + + public void demonstrateAGraphStageWithATimer() throws Exception { + // tests: + Future result = + Source.from(Arrays.asList(1, 2, 3)) + .via(new TimedGate<>(Duration.create(2, "seconds"))) + .takeWithin(Duration.create(250, "millis")) + .runFold(0, (n, sum) -> n + sum, mat); + + assertEquals(new Integer(1), Await.result(result, Duration.create(3, "seconds"))); + } + + + //#materialized + public class FirstValue extends GraphStageWithMaterializedValue, Future> { + + public final Inlet in = Inlet.create("FirstValue.in"); + public final Outlet out = Outlet.create("FirstValue.out"); + + private final FlowShape shape = FlowShape.of(in, out); + @Override + public FlowShape shape() { + return shape; + } + + @Override + public Tuple2> createLogicAndMaterializedValue(Attributes inheritedAttributes) { + Promise promise = Futures.promise(); + + GraphStageLogic logic = new GraphStageLogic(shape) { + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + promise.success(elem); + push(out, elem); + + // replace handler with one just forwarding + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + push(out, grab(in)); + } + }); + } + }); + + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + pull(in); + } + }); + } + }; + + return new Tuple2(logic, promise.future()); + } + } + //#materialized + + public void demonstrateACustomMaterializedValue() throws Exception { + // tests: + RunnableGraph> flow = Source.from(Arrays.asList(1, 2, 3)) + .viaMat(new FirstValue(), Keep.right()) + .to(Sink.ignore()); + + Future result = flow.run(mat); + + assertEquals(new Integer(1), Await.result(result, Duration.create(3, "seconds"))); + } + + + //#detached + public class TwoBuffer extends GraphStage> { + + public final Inlet in = Inlet.create("TwoBuffer.in"); + public final Outlet out = Outlet.create("TwoBuffer.out"); + + private final FlowShape shape = FlowShape.of(in, out); + + @Override + public FlowShape shape() { + return shape; + } + + @Override + public GraphStageLogic createLogic(Attributes inheritedAttributes) { + return new GraphStageLogic(shape) { + + private final int SIZE = 2; + private Queue buffer = new ArrayDeque<>(SIZE); + private boolean downstreamWaiting = false; + + private boolean isBufferFull() { + return buffer.size() == SIZE; + } + + @Override + public void preStart() { + // a detached stage needs to start upstream demand + // itself as it is not triggered by downstream demand + pull(in); + } + + { + setHandler(in, new AbstractInHandler() { + @Override + public void onPush() { + A elem = grab(in); + buffer.add(elem); + if (downstreamWaiting) { + downstreamWaiting = false; + A bufferedElem = buffer.poll(); + push(out, bufferedElem); + } + if (!isBufferFull()) { + pull(in); + } + } + + @Override + public void onUpstreamFinish() { + if (!buffer.isEmpty()) { + // emit the rest if possible + emitMultiple(out, buffer.iterator()); + } + completeStage(); + } + }); + + + setHandler(out, new AbstractOutHandler() { + @Override + public void onPull() { + if (buffer.isEmpty()) { + downstreamWaiting = true; + } else { + A elem = buffer.poll(); + push(out, elem); + } + if (!isBufferFull() && !hasBeenPulled(in)) { + pull(in); + } + } + }); + } + }; + + } + } + //#detached + + + public void demonstrateADetachedGraphStage() throws Exception { + // tests: + Future result1 = Source.from(Arrays.asList(1, 2, 3)) + .via(new TwoBuffer<>()) + .runFold(0, (acc, n) -> acc + n, mat); + + assertEquals(new Integer(6), Await.result(result1, Duration.create(3, "seconds"))); + + TestSubscriber.ManualProbe subscriber = TestSubscriber.manualProbe(system); + TestPublisher.Probe publisher = TestPublisher.probe(0, system); + RunnableGraph flow2 = + Source.fromPublisher(publisher) + .via(new TwoBuffer<>()) + .to(Sink.fromSubscriber(subscriber)); + + flow2.run(mat); + + Subscription sub = subscriber.expectSubscription(); + // this happens even though the subscriber has not signalled any demand + publisher.sendNext(1); + publisher.sendNext(2); + + sub.cancel(); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/IntegrationDocTest.java b/akka-docs/rst/java/code/docs/stream/IntegrationDocTest.java new file mode 100644 index 0000000000..928aaf269e --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/IntegrationDocTest.java @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ + +package docs.stream; + +import akka.actor.*; +import akka.dispatch.Futures; +import akka.dispatch.MessageDispatcher; +import akka.japi.pf.ReceiveBuilder; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; +import akka.testkit.TestProbe; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Author; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Tweet; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.ExecutionContext; +import scala.concurrent.Future; +import scala.runtime.BoxedUnit; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import static akka.pattern.Patterns.ask; +import static docs.stream.TwitterStreamQuickstartDocTest.Model.AKKA; +import static docs.stream.TwitterStreamQuickstartDocTest.Model.tweets; +import static junit.framework.TestCase.assertTrue; + +public class IntegrationDocTest { + + private static final SilenceSystemOut.System System = SilenceSystemOut.get(); + + static ActorSystem system; + + @BeforeClass + public static void setup() { + final Config config = ConfigFactory.parseString("" + + "blocking-dispatcher { \n" + + " executor = thread-pool-executor \n" + + " thread-pool-executor { \n" + + " core-pool-size-min = 10 \n" + + " core-pool-size-max = 10 \n" + + " } \n" + + "} \n" + + "akka.actor.default-mailbox.mailbox-type = akka.dispatch.UnboundedMailbox\n"); + + system = ActorSystem.create("ActorPublisherDocTest", config); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + class AddressSystem { + //#email-address-lookup + public Future> lookupEmail(String handle) + //#email-address-lookup + { + return Futures.successful(Optional.of(handle + "@somewhere.com")); + } + + //#phone-lookup + public Future> lookupPhoneNumber(String handle) + //#phone-lookup + { + return Futures.successful(Optional.of("" + handle.hashCode())); + } + } + + class AddressSystem2 { + //#email-address-lookup2 + public Future lookupEmail(String handle) + //#email-address-lookup2 + { + return Futures.successful(handle + "@somewhere.com"); + } + } + + static class Email { + public final String to; + public final String title; + public final String body; + + public Email(String to, String title, String body) { + this.to = to; + this.title = title; + this.body = body; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Email email = (Email) o; + + if (body != null ? !body.equals(email.body) : email.body != null) { + return false; + } + if (title != null ? !title.equals(email.title) : email.title != null) { + return false; + } + if (to != null ? !to.equals(email.to) : email.to != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = to != null ? to.hashCode() : 0; + result = 31 * result + (title != null ? title.hashCode() : 0); + result = 31 * result + (body != null ? body.hashCode() : 0); + return result; + } + } + + static class TextMessage { + public final String to; + public final String body; + + TextMessage(String to, String body) { + this.to = to; + this.body = body; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TextMessage that = (TextMessage) o; + + if (body != null ? !body.equals(that.body) : that.body != null) { + return false; + } + if (to != null ? !to.equals(that.to) : that.to != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = to != null ? to.hashCode() : 0; + result = 31 * result + (body != null ? body.hashCode() : 0); + return result; + } + } + + static class EmailServer { + public final ActorRef probe; + + public EmailServer(ActorRef probe) { + this.probe = probe; + } + + //#email-server-send + public Future send(Email email) { + // ... + //#email-server-send + probe.tell(email.to, ActorRef.noSender()); + return Futures.successful(email); + //#email-server-send + } + //#email-server-send + } + + + static class SmsServer { + public final ActorRef probe; + + public SmsServer(ActorRef probe) { + this.probe = probe; + } + + //#sms-server-send + public boolean send(TextMessage text) { + // ... + //#sms-server-send + probe.tell(text.to, ActorRef.noSender()); + //#sms-server-send + return true; + } + //#sms-server-send + } + + static class Save { + public final Tweet tweet; + + Save(Tweet tweet) { + this.tweet = tweet; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Save save = (Save) o; + + if (tweet != null ? !tweet.equals(save.tweet) : save.tweet != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return tweet != null ? tweet.hashCode() : 0; + } + } + static class SaveDone { + public static SaveDone INSTANCE = new SaveDone(); + private SaveDone() { + } + } + + + static class DatabaseService extends AbstractActor { + public final ActorRef probe; + + DatabaseService(ActorRef probe) { + this.probe = probe; + + receive(ReceiveBuilder.match(Save.class, s -> { + probe.tell(s.tweet.author.handle, ActorRef.noSender()); + sender().tell(SaveDone.INSTANCE, self()); + }).build()); + } + } + + //#sometimes-slow-service + static class SometimesSlowService { + private final ExecutionContext ec; + + public SometimesSlowService(ExecutionContext ec) { + this.ec = ec; + } + + private final AtomicInteger runningCount = new AtomicInteger(); + + public Future convert(String s) { + System.out.println("running: " + s + "(" + runningCount.incrementAndGet() + ")"); + return Futures.future(() -> { + if (!s.isEmpty() && Character.isLowerCase(s.charAt(0))) + Thread.sleep(500); + else + Thread.sleep(20); + System.out.println("completed: " + s + "(" + runningCount.decrementAndGet() + ")"); + return s.toUpperCase(); + }, ec); + } + } + //#sometimes-slow-service + + + @Test + public void callingExternalServiceWithMapAsync() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + final AddressSystem addressSystem = new AddressSystem(); + final EmailServer emailServer = new EmailServer(probe.ref()); + + { + //#tweet-authors + final Source authors = tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + //#tweet-authors + + //#email-addresses-mapAsync + final Source emailAddresses = authors + .mapAsync(4, author -> addressSystem.lookupEmail(author.handle)) + .filter(o -> o.isPresent()) + .map(o -> o.get()); + + //#email-addresses-mapAsync + + //#send-emails + final RunnableGraph sendEmails = emailAddresses + .mapAsync(4, address -> + emailServer.send(new Email(address, "Akka", "I like your tweet"))) + .to(Sink.ignore()); + + sendEmails.run(mat); + //#send-emails + + probe.expectMsg("rolandkuhn@somewhere.com"); + probe.expectMsg("patriknw@somewhere.com"); + probe.expectMsg("bantonsson@somewhere.com"); + probe.expectMsg("drewhk@somewhere.com"); + probe.expectMsg("ktosopl@somewhere.com"); + probe.expectMsg("mmartynas@somewhere.com"); + probe.expectMsg("akkateam@somewhere.com"); + } + }; + } + + @Test + @SuppressWarnings("unused") + public void callingExternalServiceWithMapAsyncAndSupervision() throws Exception { + new JavaTestKit(system) { + final AddressSystem2 addressSystem = new AddressSystem2(); + + { + final Source authors = tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + //#email-addresses-mapAsync-supervision + final Attributes resumeAttrib = + ActorAttributes.withSupervisionStrategy(Supervision.getResumingDecider()); + final Flow lookupEmail = + Flow.of(Author.class) + .mapAsync(4, author -> addressSystem.lookupEmail(author.handle)) + .withAttributes(resumeAttrib); + final Source emailAddresses = authors.via(lookupEmail); + + //#email-addresses-mapAsync-supervision + } + }; + } + + @Test + public void callingExternalServiceWithMapAsyncUnordered() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + final AddressSystem addressSystem = new AddressSystem(); + final EmailServer emailServer = new EmailServer(probe.ref()); + + { + //#external-service-mapAsyncUnordered + final Source authors = + tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + final Source emailAddresses = + authors + .mapAsyncUnordered(4, author -> addressSystem.lookupEmail(author.handle)) + .filter(o -> o.isPresent()) + .map(o -> o.get()); + + final RunnableGraph sendEmails = + emailAddresses + .mapAsyncUnordered(4, address -> + emailServer.send(new Email(address, "Akka", "I like your tweet"))) + .to(Sink.ignore()); + + sendEmails.run(mat); + //#external-service-mapAsyncUnordered + } + }; + } + + @Test + public void carefulManagedBlockingWithMapAsync() throws Exception { + new JavaTestKit(system) { + final AddressSystem addressSystem = new AddressSystem(); + final EmailServer emailServer = new EmailServer(getRef()); + final SmsServer smsServer = new SmsServer(getRef()); + + { + final Source authors = + tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + final Source phoneNumbers = authors.mapAsync(4, author -> addressSystem.lookupPhoneNumber(author.handle)) + .filter(o -> o.isPresent()) + .map(o -> o.get()); + + //#blocking-mapAsync + final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher"); + + final RunnableGraph sendTextMessages = + phoneNumbers + .mapAsync(4, phoneNo -> + Futures.future(() -> + smsServer.send(new TextMessage(phoneNo, "I like your tweet")), + blockingEc) + ) + .to(Sink.ignore()); + + sendTextMessages.run(mat); + //#blocking-mapAsync + + final Object[] got = receiveN(7); + final Set set = new HashSet<>(Arrays.asList(got)); + + assertTrue(set.contains(String.valueOf("rolandkuhn".hashCode()))); + assertTrue(set.contains(String.valueOf("patriknw".hashCode()))); + assertTrue(set.contains(String.valueOf("bantonsson".hashCode()))); + assertTrue(set.contains(String.valueOf("drewhk".hashCode()))); + assertTrue(set.contains(String.valueOf("ktosopl".hashCode()))); + assertTrue(set.contains(String.valueOf("mmartynas".hashCode()))); + assertTrue(set.contains(String.valueOf("akkateam".hashCode()))); + } + }; + } + + @Test + public void carefulManagedBlockingWithMap() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + final AddressSystem addressSystem = new AddressSystem(); + final EmailServer emailServer = new EmailServer(probe.ref()); + final SmsServer smsServer = new SmsServer(probe.ref()); + + { + final Source authors = + tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + final Source phoneNumbers = authors.mapAsync(4, author -> addressSystem.lookupPhoneNumber(author.handle)) + .filter(o -> o.isPresent()) + .map(o -> o.get()); + + //#blocking-map + final Flow send = + Flow.of(String.class) + .map(phoneNo -> smsServer.send(new TextMessage(phoneNo, "I like your tweet"))) + .withAttributes(ActorAttributes.dispatcher("blocking-dispatcher")); + final RunnableGraph sendTextMessages = + phoneNumbers.via(send).to(Sink.ignore()); + + sendTextMessages.run(mat); + //#blocking-map + + probe.expectMsg(String.valueOf("rolandkuhn".hashCode())); + probe.expectMsg(String.valueOf("patriknw".hashCode())); + probe.expectMsg(String.valueOf("bantonsson".hashCode())); + probe.expectMsg(String.valueOf("drewhk".hashCode())); + probe.expectMsg(String.valueOf("ktosopl".hashCode())); + probe.expectMsg(String.valueOf("mmartynas".hashCode())); + probe.expectMsg(String.valueOf("akkateam".hashCode())); + } + }; + } + + @Test + public void callingActorServiceWithMapAsync() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + final EmailServer emailServer = new EmailServer(probe.ref()); + + final ActorRef database = system.actorOf(Props.create(DatabaseService.class, probe.ref()), "db"); + + { + //#save-tweets + final Source akkaTweets = tweets.filter(t -> t.hashtags().contains(AKKA)); + + final RunnableGraph saveTweets = + akkaTweets + .mapAsync(4, tweet -> ask(database, new Save(tweet), 300)) + .to(Sink.ignore()); + //#save-tweets + + saveTweets.run(mat); + + probe.expectMsg("rolandkuhn"); + probe.expectMsg("patriknw"); + probe.expectMsg("bantonsson"); + probe.expectMsg("drewhk"); + probe.expectMsg("ktosopl"); + probe.expectMsg("mmartynas"); + probe.expectMsg("akkateam"); + } + }; + } + + @Test + public void illustrateOrderingAndParallelismOfMapAsync() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + final EmailServer emailServer = new EmailServer(probe.ref()); + + class MockSystem { + class Println { + public void println(T s) { + if (s.toString().startsWith("after:")) + probe.ref().tell(s, ActorRef.noSender()); + } + } + + public final Println out = new Println(); + } + private final MockSystem System = new MockSystem(); + + { + //#sometimes-slow-mapAsync + final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher"); + final SometimesSlowService service = new SometimesSlowService(blockingEc); + + final ActorMaterializer mat = ActorMaterializer.create( + ActorMaterializerSettings.create(system).withInputBuffer(4, 4), system); + + Source.from(Arrays.asList("a", "B", "C", "D", "e", "F", "g", "H", "i", "J")) + .map(elem -> { System.out.println("before: " + elem); return elem; }) + .mapAsync(4, service::convert) + .runForeach(elem -> System.out.println("after: " + elem), mat); + //#sometimes-slow-mapAsync + + probe.expectMsg("after: A"); + probe.expectMsg("after: B"); + probe.expectMsg("after: C"); + probe.expectMsg("after: D"); + probe.expectMsg("after: E"); + probe.expectMsg("after: F"); + probe.expectMsg("after: G"); + probe.expectMsg("after: H"); + probe.expectMsg("after: I"); + probe.expectMsg("after: J"); + } + }; + } + + @Test + public void illustrateOrderingAndParallelismOfMapAsyncUnordered() throws Exception { + new JavaTestKit(system) { + final EmailServer emailServer = new EmailServer(getRef()); + + class MockSystem { + class Println { + public void println(T s) { + if (s.toString().startsWith("after:")) + getRef().tell(s, ActorRef.noSender()); + } + } + + public final Println out = new Println(); + } + private final MockSystem System = new MockSystem(); + + { + //#sometimes-slow-mapAsyncUnordered + final MessageDispatcher blockingEc = system.dispatchers().lookup("blocking-dispatcher"); + final SometimesSlowService service = new SometimesSlowService(blockingEc); + + final ActorMaterializer mat = ActorMaterializer.create( + ActorMaterializerSettings.create(system).withInputBuffer(4, 4), system); + + Source.from(Arrays.asList("a", "B", "C", "D", "e", "F", "g", "H", "i", "J")) + .map(elem -> { System.out.println("before: " + elem); return elem; }) + .mapAsyncUnordered(4, service::convert) + .runForeach(elem -> System.out.println("after: " + elem), mat); + //#sometimes-slow-mapAsyncUnordered + + final Object[] got = receiveN(10); + final Set set = new HashSet<>(Arrays.asList(got)); + + assertTrue(set.contains("after: A")); + assertTrue(set.contains("after: B")); + assertTrue(set.contains("after: C")); + assertTrue(set.contains("after: D")); + assertTrue(set.contains("after: E")); + assertTrue(set.contains("after: F")); + assertTrue(set.contains("after: G")); + assertTrue(set.contains("after: H")); + assertTrue(set.contains("after: I")); + assertTrue(set.contains("after: J")); + } + }; + } + + +} diff --git a/akka-docs/rst/java/code/docs/stream/MigrationsJava.java b/akka-docs/rst/java/code/docs/stream/MigrationsJava.java new file mode 100644 index 0000000000..7300bb66f4 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/MigrationsJava.java @@ -0,0 +1,259 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import akka.actor.ActorSystem; +import akka.actor.Cancellable; +import akka.http.javadsl.model.Uri; +import akka.dispatch.Futures; +import akka.japi.function.Creator; +import akka.japi.Pair; +import akka.japi.function.Function; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.util.ByteString; +import scala.Option; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.concurrent.Promise; +import scala.runtime.BoxedUnit; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeUnit; +import java.nio.charset.Charset; + +public class MigrationsJava { + + // This is compile-only code, no need for actually running anything. + public static ActorMaterializer mat = null; + public static ActorSystem sys = null; + + public static class SomeInputStream extends InputStream { + public SomeInputStream() { + } + + @Override + public int read() throws IOException { + return 0; + } + } + + public static class SomeOutputStream extends OutputStream { + @Override + public void write(int b) throws IOException { + return; + } + } + + public static void main(String[] args) { + + Outlet outlet = null; + + Outlet outlet1 = null; + Outlet outlet2 = null; + + Inlet inlet = null; + + Inlet inlet1 = null; + Inlet inlet2 = null; + + Flow flow = Flow.of(Integer.class); + Flow flow1 = Flow.of(Integer.class); + Flow flow2 = Flow.of(Integer.class); + + Promise> promise = null; + + + { + Graph, BoxedUnit> graphSource = null; + Graph, BoxedUnit> graphSink = null; + Graph, BoxedUnit> graphFlow = null; + + //#flow-wrap + Source source = Source.fromGraph(graphSource); + Sink sink = Sink.fromGraph(graphSink); + Flow aflow = Flow.fromGraph(graphFlow); + Flow.fromSinkAndSource(Sink.head(), Source.single(0)); + Flow.fromSinkAndSourceMat(Sink.head(), Source.single(0), Keep.left()); + //#flow-wrap + + Graph, BoxedUnit> bidiGraph = null; + + //#bidi-wrap + BidiFlow bidiFlow = + BidiFlow.fromGraph(bidiGraph); + BidiFlow.fromFlows(flow1, flow2); + BidiFlow.fromFlowsMat(flow1, flow2, Keep.both()); + //#bidi-wrap + + } + + { + //#graph-create + GraphDSL.create(builder -> { + //... + return ClosedShape.getInstance(); + }); + + GraphDSL.create(builder -> { + //... + return new FlowShape<>(inlet, outlet); + }); + //#graph-create + } + + { + //#graph-create-2 + GraphDSL.create(builder -> { + //... + return SourceShape.of(outlet); + }); + + GraphDSL.create(builder -> { + //... + return SinkShape.of(inlet); + }); + + GraphDSL.create(builder -> { + //... + return FlowShape.of(inlet, outlet); + }); + + GraphDSL.create(builder -> { + //... + return BidiShape.of(inlet1, outlet1, inlet2, outlet2); + }); + //#graph-create-2 + } + + { + //#graph-builder + GraphDSL.create(builder -> { + builder.from(outlet).toInlet(inlet); + builder.from(outlet).via(builder.add(flow)).toInlet(inlet); + builder.from(builder.add(Source.single(0))).to(builder.add(Sink.head())); + //... + return ClosedShape.getInstance(); + }); + //#graph-builder + } + + //#source-creators + Source>> src = Source.maybe(); + // Complete the promise with an empty option to emulate the old lazyEmpty + promise.trySuccess(scala.Option.empty()); + + final Source ticks = Source.tick( + FiniteDuration.create(0, TimeUnit.MILLISECONDS), + FiniteDuration.create(200, TimeUnit.MILLISECONDS), + "tick"); + + final Source pubSource = + Source.fromPublisher(TestPublisher.manualProbe(true, sys)); + + final Source futSource = + Source.fromFuture(Futures.successful(42)); + + final Source> subSource = + Source.asSubscriber(); + //#source-creators + + //#sink-creators + final Sink subSink = + Sink.fromSubscriber(TestSubscriber.manualProbe(sys)); + //#sink-creators + + //#sink-as-publisher + final Sink> pubSink = + Sink.asPublisher(false); + + final Sink> pubSinkFanout = + Sink.asPublisher(true); + //#sink-as-publisher + + //#empty-flow + Flow emptyFlow = Flow.create(); + // or + Flow emptyFlow2 = Flow.of(Integer.class); + //#empty-flow + + //#flatMapConcat + Flow.>create(). + flatMapConcat(i -> i); + //#flatMapConcat + + //#group-flatten + Flow.of(Integer.class) + .groupBy(2, in -> in % 2) // the first parameter sets max number of substreams + .map(subIn -> + 3) + .concatSubstreams(); + //#group-flatten + + final int maxDistinctWords = 1000; + //#group-fold + Flow.of(String.class) + .groupBy(maxDistinctWords, i -> i) + .fold(Pair.create("", 0), (pair, word) -> Pair.create(word, pair.second() + 1)) + .mergeSubstreams(); + //#group-fold + + Uri uri = null; + //#raw-query + final akka.japi.Option theRawQueryString = uri.rawQueryString(); + //#raw-query + + //#query-param + final akka.japi.Option aQueryParam = uri.query().get("a"); + //#query-param + + //#file-source-sink + final Source> fileSrc = + FileIO.fromFile(new File(".")); + + final Source> otherFileSrc = + FileIO.fromFile(new File("."), 1024); + + final Sink> fileSink = + FileIO.toFile(new File(".")); + //#file-source-sink + + //#input-output-stream-source-sink + final Source> inputStreamSrc = + StreamConverters.fromInputStream((Creator) () -> new SomeInputStream()); + + final Source> otherInputStreamSrc = + StreamConverters.fromInputStream((Creator) () -> new SomeInputStream(), 1024); + + final Sink> outputStreamSink = + StreamConverters.fromOutputStream((Creator) () -> new SomeOutputStream()); + //#input-output-stream-source-sink + + + //#output-input-stream-source-sink + final FiniteDuration timeout = FiniteDuration.Zero(); + + final Source outputStreamSrc = + StreamConverters.asOutputStream(); + + final Source otherOutputStreamSrc = + StreamConverters.asOutputStream(timeout); + + final Sink someInputStreamSink = + StreamConverters.asInputStream(); + + final Sink someOtherInputStreamSink = + StreamConverters.asInputStream(timeout); + //#output-input-stream-source-sink + + } + +} \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/stream/RateTransformationDocTest.java b/akka-docs/rst/java/code/docs/stream/RateTransformationDocTest.java new file mode 100644 index 0000000000..49c4dd3675 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/RateTransformationDocTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ + +package docs.stream; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.DoubleStream; +import java.util.stream.Stream; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.japi.tuple.Tuple3; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.stream.testkit.javadsl.TestSource; +import akka.testkit.JavaTestKit; +import akka.testkit.TestLatch; +import scala.collection.Iterator; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; +import scala.util.Random; + +public class RateTransformationDocTest { + + private static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RateTransformationDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final Random r = new Random(); + + @Test + public void conflateShouldSummarize() throws Exception { + //#conflate-summarize + final Flow, BoxedUnit> statsFlow = + Flow.of(Double.class) + .conflate(elem -> Collections.singletonList(elem), (acc, elem) -> { + return Stream + .concat(acc.stream(), Collections.singletonList(elem).stream()) + .collect(Collectors.toList()); + }) + .map(s -> { + final Double mean = s.stream().mapToDouble(d -> d).sum() / s.size(); + final DoubleStream se = s.stream().mapToDouble(x -> Math.pow(x - mean, 2)); + final Double stdDev = Math.sqrt(se.sum() / s.size()); + return new Tuple3<>(stdDev, mean, s.size()); + }); + //#conflate-summarize + + final Future>> fut = Source.repeat(0).map(i -> r.nextGaussian()) + .via(statsFlow) + .grouped(10) + .runWith(Sink.head(), mat); + + final Duration timeout = Duration.create(100, TimeUnit.MILLISECONDS); + Await.result(fut, timeout); + } + + @Test + public void conflateShouldSample() throws Exception { + //#conflate-sample + final Double p = 0.01; + final Flow sampleFlow = Flow.of(Double.class) + .conflate(elem -> Collections.singletonList(elem), (acc, elem) -> { + if (r.nextDouble() < p) { + return Stream + .concat(acc.stream(), Collections.singletonList(elem).stream()) + .collect(Collectors.toList()); + } + return acc; + }) + .mapConcat(d -> d); + //#conflate-sample + + final Future fut = Source.from(new ArrayList(Collections.nCopies(1000, 1.0))) + .via(sampleFlow) + .runWith(Sink.fold(0.0, (agg, next) -> agg + next), mat); + + final Duration timeout = Duration.create(1, TimeUnit.SECONDS); + final Double count = Await.result(fut, timeout); + } + + @Test + public void expandShouldRepeatLast() throws Exception { + //#expand-last + final Flow lastFlow = Flow.of(Double.class) + .expand(d -> d, s -> new Pair<>(s, s)); + //#expand-last + + final Pair, Future>> probeFut = TestSource. probe(system) + .via(lastFlow) + .grouped(10) + .toMat(Sink.head(), Keep.both()) + .run(mat); + + final TestPublisher.Probe probe = probeFut.first(); + final Future> fut = probeFut.second(); + probe.sendNext(1.0); + final Duration timeout = Duration.create(1, TimeUnit.SECONDS); + final List expanded = Await.result(fut, timeout); + assertEquals(expanded.size(), 10); + assertEquals(expanded.stream().mapToDouble(d -> d).sum(), 10, 0.1); + } + + @Test + public void expandShouldTrackDrift() throws Exception { + @SuppressWarnings("unused") + //#expand-drift + final Flow, BoxedUnit> driftFlow = Flow.of(Double.class) + .expand(d -> new Pair(d, 0), t -> { + return new Pair<>(t, new Pair<>(t.first(), t.second() + 1)); + }); + //#expand-drift + final TestLatch latch = new TestLatch(2, system); + final Flow, BoxedUnit> realDriftFlow = Flow.of(Double.class) + .expand(d -> { latch.countDown(); return new Pair(d, 0); }, t -> { + return new Pair<>(t, new Pair<>(t.first(), t.second() + 1)); + }); + + final Pair, TestSubscriber.Probe>> pubSub = TestSource. probe(system) + .via(realDriftFlow) + .toMat(TestSink.> probe(system), Keep.both()) + .run(mat); + + final TestPublisher.Probe pub = pubSub.first(); + final TestSubscriber.Probe> sub = pubSub.second(); + + sub.request(1); + pub.sendNext(1.0); + sub.expectNext(new Pair<>(1.0, 0)); + + sub.requestNext(new Pair<>(1.0, 1)); + sub.requestNext(new Pair<>(1.0, 2)); + + pub.sendNext(2.0); + Await.ready(latch, Duration.create(1, TimeUnit.SECONDS)); + sub.requestNext(new Pair<>(2.0, 0)); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/ReactiveStreamsDocTest.java b/akka-docs/rst/java/code/docs/stream/ReactiveStreamsDocTest.java new file mode 100644 index 0000000000..2832a85864 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/ReactiveStreamsDocTest.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ + +package docs.stream; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.japi.function.Creator; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; +import akka.testkit.TestProbe; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Author; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Tweet; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +//#imports +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Processor; +//#imports +import org.reactivestreams.Subscription; + +import scala.runtime.BoxedUnit; + +import java.lang.Exception; + +import static docs.stream.ReactiveStreamsDocTest.Fixture.Data.authors; +import static docs.stream.TwitterStreamQuickstartDocTest.Model.AKKA; + +public class ReactiveStreamsDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("ReactiveStreamsDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + + static class Fixture { + // below class additionally helps with aligning code includes nicely + static class Data { + + static //#authors + final Flow authors = Flow.of(Tweet.class) + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + + //#authors + } + + static interface RS { + //#tweets-publisher + Publisher tweets(); + //#tweets-publisher + + //#author-storage-subscriber + Subscriber storage(); + //#author-storage-subscriber + + //#author-alert-subscriber + Subscriber alert(); + //#author-alert-subscriber + } + } + + final TestProbe storageProbe = TestProbe.apply(system); + final TestProbe alertProbe = TestProbe.apply(system); + + final Fixture.RS rs = new Fixture.RS() { + @Override + public Publisher tweets() { + return TwitterStreamQuickstartDocTest.Model.tweets.runWith(Sink.asPublisher(false), mat); + } + + /** + * This is a minimal version of SubscriberProbe, + * which lives in akka-stream-testkit (test scope) and for + * now wanted to avoid setting up (test -> compile) dependency for maven). + * + * TODO: Once SubscriberProbe is easily used here replace this MPS with it. + */ + class MinimalProbeSubscriber implements Subscriber { + + private final ActorRef ref; + + public MinimalProbeSubscriber(ActorRef ref) { + this.ref = ref; + } + + @Override + public void onSubscribe(Subscription s) { + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(T t) { + ref.tell(t, ActorRef.noSender()); + } + + @Override + public void onError(Throwable t) { + ref.tell(t, ActorRef.noSender()); + } + + @Override + public void onComplete() { + ref.tell("complete", ActorRef.noSender()); + } + } + + @Override + public Subscriber storage() { + return new MinimalProbeSubscriber<>(storageProbe.ref()); + } + + @Override + public Subscriber alert() { + return new MinimalProbeSubscriber<>(alertProbe.ref()); + } + }; + + + @Test + public void reactiveStreamsPublisherViaFlowToSubscriber() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + + { + //#connect-all + Source.fromPublisher(rs.tweets()) + .via(authors) + .to(Sink.fromSubscriber(rs.storage())); + //#connect-all + } + }; + } + + @Test + public void flowAsPublisherAndSubscriber() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + + { + //#flow-publisher-subscriber + final Processor processor = + authors.toProcessor().run(mat); + + + rs.tweets().subscribe(processor); + processor.subscribe(rs.storage()); + //#flow-publisher-subscriber + + assertStorageResult(); + } + }; + } + + @Test + public void sourceAsPublisher() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + + { + //#source-publisher + final Publisher authorPublisher = + Source.fromPublisher(rs.tweets()).via(authors).runWith(Sink.asPublisher(false), mat); + + authorPublisher.subscribe(rs.storage()); + //#source-publisher + + assertStorageResult(); + } + }; + } + + @Test + public void sourceAsFanoutPublisher() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + + { + //#source-fanoutPublisher + final Publisher authorPublisher = + Source.fromPublisher(rs.tweets()) + .via(authors) + .runWith(Sink.asPublisher(true), mat); + + authorPublisher.subscribe(rs.storage()); + authorPublisher.subscribe(rs.alert()); + //#source-fanoutPublisher + + assertStorageResult(); + } + }; + } + + @Test + public void sinkAsSubscriber() throws Exception { + new JavaTestKit(system) { + final TestProbe probe = new TestProbe(system); + + { + //#sink-subscriber + final Subscriber storage = rs.storage(); + + final Subscriber tweetSubscriber = + authors + .to(Sink.fromSubscriber(storage)) + .runWith(Source.asSubscriber(), mat); + + rs.tweets().subscribe(tweetSubscriber); + //#sink-subscriber + + assertStorageResult(); + } + }; + } + + @Test + public void useProcessor() throws Exception { + new JavaTestKit(system) { + { + //#use-processor + // An example Processor factory + final Creator> factory = + new Creator>() { + public Processor create() { + return Flow.of(Integer.class).toProcessor().run(mat); + } + }; + + final Flow flow = Flow.fromProcessor(factory); + + //#use-processor + } + }; + } + + void assertStorageResult() { + storageProbe.expectMsg(new Author("rolandkuhn")); + storageProbe.expectMsg(new Author("patriknw")); + storageProbe.expectMsg(new Author("bantonsson")); + storageProbe.expectMsg(new Author("drewhk")); + storageProbe.expectMsg(new Author("ktosopl")); + storageProbe.expectMsg(new Author("mmartynas")); + storageProbe.expectMsg(new Author("akkateam")); + storageProbe.expectMsg("complete"); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/SilenceSystemOut.java b/akka-docs/rst/java/code/docs/stream/SilenceSystemOut.java new file mode 100644 index 0000000000..b4b17162ea --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/SilenceSystemOut.java @@ -0,0 +1,64 @@ +package docs.stream; + +import akka.actor.ActorRef; + +import java.util.function.Predicate; + +/** + * Acts as if `System.out.println()` yet swallows all messages. Useful for putting printlines in examples yet without poluting the build with them. + */ +public class SilenceSystemOut { + + private SilenceSystemOut() { + } + + public static System get() { + return new System(new System.Println() { + @Override + public void println(String s) { + // ignore + } + }); + } + + public static System get(ActorRef probe) { + return new System(new System.Println() { + @Override + public void println(String s) { + probe.tell(s, ActorRef.noSender()); + } + }); + } + + public static System get(Predicate filter, ActorRef probe) { + return new System(new System.Println() { + @Override + public void println(String s) { + if (filter.test(s)) + probe.tell(s, ActorRef.noSender()); + } + }); + } + + public static class System { + public final Println out; + + public System(Println out) { + this.out = out; + } + + public static abstract class Println { + public abstract void println(String s); + + public void println(Object s) { + println(s.toString()); + } + + public void printf(String format, Object... args) { + println(String.format(format, args)); + } + } + + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/StreamBuffersRateDocTest.java b/akka-docs/rst/java/code/docs/stream/StreamBuffersRateDocTest.java new file mode 100644 index 0000000000..36aee47593 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/StreamBuffersRateDocTest.java @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2014 Typesafe Inc. + */ +package docs.stream; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; +import akka.actor.ActorSystem; +import akka.actor.Cancellable; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; + +public class StreamBuffersRateDocTest { + + static class Job {} + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("StreamBufferRateDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final SilenceSystemOut.System System = SilenceSystemOut.get(); + + @Test + public void demonstratePipelining() { + //#pipelining + Source.from(Arrays.asList(1, 2, 3)) + .map(i -> {System.out.println("A: " + i); return i;}) + .map(i -> {System.out.println("B: " + i); return i;}) + .map(i -> {System.out.println("C: " + i); return i;}) + .runWith(Sink.ignore(), mat); + //#pipelining + } + + @Test + @SuppressWarnings("unused") + public void demonstrateBufferSizes() { + //#materializer-buffer + final Materializer materializer = ActorMaterializer.create( + ActorMaterializerSettings.create(system) + .withInputBuffer(64, 64), system); + //#materializer-buffer + + //#section-buffer + final Flow flow1 = + Flow.of(Integer.class) + .map(elem -> elem * 2) // the buffer size of this map is 1 + .withAttributes(Attributes.inputBuffer(1, 1)); + final Flow flow2 = + flow1.via( + Flow.of(Integer.class) + .map(elem -> elem / 2)); // the buffer size of this map is the default + //#section-buffer + } + + @Test + public void demonstrateBufferAbstractionLeak() { + //#buffering-abstraction-leak + final FiniteDuration oneSecond = + FiniteDuration.create(1, TimeUnit.SECONDS); + final Source msgSource = + Source.tick(oneSecond, oneSecond, "message!"); + final Source tickSource = + Source.tick(oneSecond.mul(3), oneSecond.mul(3), "tick"); + final Flow conflate = + Flow.of(String.class).conflate( + first -> 1, (count, elem) -> count + 1); + + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final FanInShape2 zipper = + b.add(ZipWith.create((String tick, Integer count) -> count)); + b.from(b.add(msgSource)).via(b.add(conflate)).toInlet(zipper.in1()); + b.from(b.add(tickSource)).toInlet(zipper.in0()); + b.from(zipper.out()).to(b.add(Sink.foreach(elem -> System.out.println(elem)))); + return ClosedShape.getInstance(); + })).run(mat); + //#buffering-abstraction-leak + } + + @Test + public void demonstrateExplicitBuffers() { + final Source inboundJobsConnector = Source.empty(); + //#explicit-buffers-backpressure + // Getting a stream of jobs from an imaginary external system as a Source + final Source jobs = inboundJobsConnector; + jobs.buffer(1000, OverflowStrategy.backpressure()); + //#explicit-buffers-backpressure + + //#explicit-buffers-droptail + jobs.buffer(1000, OverflowStrategy.dropTail()); + //#explicit-buffers-droptail + + //#explicit-buffers-dropnew + jobs.buffer(1000, OverflowStrategy.dropNew()); + //#explicit-buffers-dropnew + + //#explicit-buffers-drophead + jobs.buffer(1000, OverflowStrategy.dropHead()); + //#explicit-buffers-drophead + + //#explicit-buffers-dropbuffer + jobs.buffer(1000, OverflowStrategy.dropBuffer()); + //#explicit-buffers-dropbuffer + + //#explicit-buffers-fail + jobs.buffer(1000, OverflowStrategy.fail()); + //#explicit-buffers-fail + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/StreamPartialFlowGraphDocTest.java b/akka-docs/rst/java/code/docs/stream/StreamPartialFlowGraphDocTest.java new file mode 100644 index 0000000000..bd81441a6c --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/StreamPartialFlowGraphDocTest.java @@ -0,0 +1,176 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import static org.junit.Assert.assertEquals; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; +import akka.actor.*; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; + +public class StreamPartialFlowGraphDocTest { + + static ActorSystem system; + + + @BeforeClass + public static void setup() { + system = ActorSystem.create("StreamPartialFlowGraphDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void demonstrateBuildWithOpenPorts() throws Exception { + //#simple-partial-flow-graph + final Graph, BoxedUnit> zip = + ZipWith.create((Integer left, Integer right) -> Math.max(left, right)); + + final Graph, BoxedUnit> pickMaxOfThree = + GraphDSL.create(builder -> { + final FanInShape2 zip1 = builder.add(zip); + final FanInShape2 zip2 = builder.add(zip); + + builder.from(zip1.out()).toInlet(zip2.in0()); + // return the shape, which has three inputs and one output + return new UniformFanInShape(zip2.out(), + new Inlet[] {zip1.in0(), zip1.in1(), zip2.in1()}); + }); + + final Sink> resultSink = Sink.head(); + + final RunnableGraph> g = + RunnableGraph.>fromGraph( + GraphDSL.create(resultSink, (builder, sink) -> { + // import the partial flow graph explicitly + final UniformFanInShape pm = builder.add(pickMaxOfThree); + + builder.from(builder.add(Source.single(1))).toInlet(pm.in(0)); + builder.from(builder.add(Source.single(2))).toInlet(pm.in(1)); + builder.from(builder.add(Source.single(3))).toInlet(pm.in(2)); + builder.from(pm.out()).to(sink); + return ClosedShape.getInstance(); + })); + + final Future max = g.run(mat); + //#simple-partial-flow-graph + assertEquals(Integer.valueOf(3), Await.result(max, Duration.create(3, TimeUnit.SECONDS))); + } + + //#source-from-partial-flow-graph + // first create an indefinite source of integer numbers + class Ints implements Iterator { + private int next = 0; + @Override + public boolean hasNext() { + return true; + } + @Override + public Integer next() { + return next++; + } + } + //#source-from-partial-flow-graph + + @Test + public void demonstrateBuildSourceFromPartialFlowGraphCreate() throws Exception { + //#source-from-partial-flow-graph + final Source ints = Source.fromIterator(() -> new Ints()); + + final Source, BoxedUnit> pairs = Source.fromGraph( + GraphDSL.create( + builder -> { + final FanInShape2> zip = + builder.add(Zip.create()); + + builder.from(builder.add(ints.filter(i -> i % 2 == 0))).toInlet(zip.in0()); + builder.from(builder.add(ints.filter(i -> i % 2 == 1))).toInlet(zip.in1()); + + return SourceShape.of(zip.out()); + })); + + final Future> firstPair = + pairs.runWith(Sink.>head(), mat); + //#source-from-partial-flow-graph + assertEquals(new Pair<>(0, 1), Await.result(firstPair, Duration.create(3, TimeUnit.SECONDS))); + } + + @Test + public void demonstrateBuildFlowFromPartialFlowGraphCreate() throws Exception { + //#flow-from-partial-flow-graph + final Flow, BoxedUnit> pairs = Flow.fromGraph(GraphDSL.create( + b -> { + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final FanInShape2> zip = + b.add(Zip.create()); + + b.from(bcast).toInlet(zip.in0()); + b.from(bcast).via(b.add(Flow.of(Integer.class).map(i -> i.toString()))).toInlet(zip.in1()); + + return FlowShape.of(bcast.in(), zip.out()); + })); + + //#flow-from-partial-flow-graph + final Future> matSink = + //#flow-from-partial-flow-graph + Source.single(1).via(pairs).runWith(Sink.>head(), mat); + //#flow-from-partial-flow-graph + + assertEquals(new Pair<>(1, "1"), Await.result(matSink, Duration.create(3, TimeUnit.SECONDS))); + } + + + @Test + public void demonstrateBuildSourceWithCombine() throws Exception { + //#source-combine + Source source1 = Source.single(1); + Source source2 = Source.single(2); + + final Source sources = Source.combine(source1, source2, new ArrayList<>(), + i -> Merge.create(i)); + //#source-combine + final Future result= + //#source-combine + sources.runWith(Sink.fold(0, (a,b) -> a + b), mat); + //#source-combine + + assertEquals(Integer.valueOf(3), Await.result(result, Duration.create(3, TimeUnit.SECONDS))); + } + + @Test + public void demonstrateBuildSinkWithCombine() throws Exception { + final JavaTestKit probe = new JavaTestKit(system); + ActorRef actorRef = probe.getRef(); + + //#sink-combine + Sink sendRmotely = Sink.actorRef(actorRef, "Done"); + Sink> localProcessing = Sink.foreach(a -> { /*do something useful*/ } ); + Sink sinks = Sink.combine(sendRmotely,localProcessing, new ArrayList<>(), a -> Broadcast.create(a)); + + Source.from(Arrays.asList(new Integer[]{0, 1, 2})).runWith(sinks, mat); + //#sink-combine + probe.expectMsgEquals(0); + probe.expectMsgEquals(1); + probe.expectMsgEquals(2); + } +} diff --git a/akka-docs/rst/java/code/docs/stream/StreamTestKitDocTest.java b/akka-docs/rst/java/code/docs/stream/StreamTestKitDocTest.java new file mode 100644 index 0000000000..11749079e9 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/StreamTestKitDocTest.java @@ -0,0 +1,229 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.*; +import static org.junit.Assert.assertEquals; + +import akka.actor.*; +import akka.dispatch.Futures; +import akka.testkit.*; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.testkit.*; +import akka.stream.testkit.javadsl.*; +import akka.testkit.TestProbe; +import scala.util.*; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; + +import scala.runtime.BoxedUnit; + +public class StreamTestKitDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("StreamTestKitDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void strictCollection() throws Exception { + //#strict-collection + final Sink> sinkUnderTest = Flow.of(Integer.class) + .map(i -> i * 2) + .toMat(Sink.fold(0, (agg, next) -> agg + next), Keep.right()); + + final Future future = Source.from(Arrays.asList(1, 2, 3, 4)) + .runWith(sinkUnderTest, mat); + final Integer result = Await.result(future, Duration.create(1, TimeUnit.SECONDS)); + assert(result == 20); + //#strict-collection + } + + @Test + public void groupedPartOfInfiniteStream() throws Exception { + //#grouped-infinite + final Source sourceUnderTest = Source.repeat(1) + .map(i -> i * 2); + + final Future> future = sourceUnderTest + .grouped(10) + .runWith(Sink.head(), mat); + final List result = + Await.result(future, Duration.create(1, TimeUnit.SECONDS)); + assertEquals(result, Collections.nCopies(10, 2)); + //#grouped-infinite + } + + @Test + public void foldedStream() throws Exception { + //#folded-stream + final Flow flowUnderTest = Flow.of(Integer.class) + .takeWhile(i -> i < 5); + + final Future future = Source.from(Arrays.asList(1, 2, 3, 4, 5, 6)) + .via(flowUnderTest).runWith(Sink.fold(0, (agg, next) -> agg + next), mat); + final Integer result = Await.result(future, Duration.create(1, TimeUnit.SECONDS)); + assert(result == 10); + //#folded-stream + } + + @Test + public void pipeToTestProbe() throws Exception { + //#pipeto-testprobe + final Source, BoxedUnit> sourceUnderTest = Source + .from(Arrays.asList(1, 2, 3, 4)) + .grouped(2); + + final TestProbe probe = new TestProbe(system); + final Future>> future = sourceUnderTest + .grouped(2) + .runWith(Sink.head(), mat); + akka.pattern.Patterns.pipe(future, system.dispatcher()).to(probe.ref()); + probe.expectMsg(Duration.create(1, TimeUnit.SECONDS), + Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4)) + ); + //#pipeto-testprobe + } + + public enum Tick { TOCK, COMPLETED }; + + @Test + public void sinkActorRef() throws Exception { + //#sink-actorref + final Source sourceUnderTest = Source.tick( + FiniteDuration.create(0, TimeUnit.MILLISECONDS), + FiniteDuration.create(200, TimeUnit.MILLISECONDS), + Tick.TOCK); + + final TestProbe probe = new TestProbe(system); + final Cancellable cancellable = sourceUnderTest + .to(Sink.actorRef(probe.ref(), Tick.COMPLETED)).run(mat); + probe.expectMsg(Duration.create(1, TimeUnit.SECONDS), Tick.TOCK); + probe.expectNoMsg(Duration.create(100, TimeUnit.MILLISECONDS)); + probe.expectMsg(Duration.create(1, TimeUnit.SECONDS), Tick.TOCK); + cancellable.cancel(); + probe.expectMsg(Duration.create(1, TimeUnit.SECONDS), Tick.COMPLETED); + //#sink-actorref + } + + @Test + public void sourceActorRef() throws Exception { + //#source-actorref + final Sink> sinkUnderTest = Flow.of(Integer.class) + .map(i -> i.toString()) + .toMat(Sink.fold("", (agg, next) -> agg + next), Keep.right()); + + final Pair> refAndFuture = + Source.actorRef(8, OverflowStrategy.fail()) + .toMat(sinkUnderTest, Keep.both()) + .run(mat); + final ActorRef ref = refAndFuture.first(); + final Future future = refAndFuture.second(); + + ref.tell(1, ActorRef.noSender()); + ref.tell(2, ActorRef.noSender()); + ref.tell(3, ActorRef.noSender()); + ref.tell(new akka.actor.Status.Success("done"), ActorRef.noSender()); + + final String result = Await.result(future, Duration.create(1, TimeUnit.SECONDS)); + assertEquals(result, "123"); + //#source-actorref + } + + @Test + public void testSinkProbe() { + //#test-sink-probe + final Source sourceUnderTest = Source.from(Arrays.asList(1, 2, 3, 4)) + .filter(elem -> elem % 2 == 0) + .map(elem -> elem * 2); + + sourceUnderTest + .runWith(TestSink.probe(system), mat) + .request(2) + .expectNext(4, 8) + .expectComplete(); + //#test-sink-probe + } + + @Test + public void testSourceProbe() { + //#test-source-probe + final Sink sinkUnderTest = Sink.cancelled(); + + TestSource.probe(system) + .toMat(sinkUnderTest, Keep.left()) + .run(mat) + .expectCancellation(); + //#test-source-probe + } + + @Test + public void injectingFailure() throws Exception { + //#injecting-failure + final Sink> sinkUnderTest = Sink.head(); + + final Pair, Future> probeAndFuture = + TestSource.probe(system) + .toMat(sinkUnderTest, Keep.both()) + .run(mat); + final TestPublisher.Probe probe = probeAndFuture.first(); + final Future future = probeAndFuture.second(); + probe.sendError(new Exception("boom")); + + Await.ready(future, Duration.create(1, TimeUnit.SECONDS)); + final Throwable exception = ((Failure)future.value().get()).exception(); + assertEquals(exception.getMessage(), "boom"); + //#injecting-failure + } + + @Test + public void testSourceAndTestSink() throws Exception { + //#test-source-and-sink + final Flow flowUnderTest = Flow.of(Integer.class) + .mapAsyncUnordered(2, sleep -> akka.pattern.Patterns.after( + Duration.create(10, TimeUnit.MILLISECONDS), + system.scheduler(), + system.dispatcher(), + Futures.successful(sleep) + )); + + final Pair, TestSubscriber.Probe> pubAndSub = + TestSource.probe(system) + .via(flowUnderTest) + .toMat(TestSink.probe(system), Keep.both()) + .run(mat); + final TestPublisher.Probe pub = pubAndSub.first(); + final TestSubscriber.Probe sub = pubAndSub.second(); + + sub.request(3); + pub.sendNext(3); + pub.sendNext(2); + pub.sendNext(1); + sub.expectNextUnordered(1, 2, 3); + + pub.sendError(new Exception("Power surge in the linear subroutine C-47!")); + final Throwable ex = sub.expectError(); + assert(ex.getMessage().contains("C-47")); + //#test-source-and-sink + } +} diff --git a/akka-docs/rst/java/code/docs/stream/TwitterStreamQuickstartDocTest.java b/akka-docs/rst/java/code/docs/stream/TwitterStreamQuickstartDocTest.java new file mode 100644 index 0000000000..9271c9b508 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/TwitterStreamQuickstartDocTest.java @@ -0,0 +1,362 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream; + +import akka.actor.ActorSystem; +import akka.dispatch.Foreach; +import akka.japi.JavaPartialFunction; +import akka.testkit.JavaTestKit; +import akka.stream.*; +import akka.stream.javadsl.*; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Author; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Hashtag; +import docs.stream.TwitterStreamQuickstartDocTest.Model.Tweet; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import static docs.stream.TwitterStreamQuickstartDocTest.Model.AKKA; +import static docs.stream.TwitterStreamQuickstartDocTest.Model.tweets; + +@SuppressWarnings("unused") +public class TwitterStreamQuickstartDocTest { + + static ActorSystem system; + + + @BeforeClass + public static void setup() { + system = ActorSystem.create("SampleActorTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + static abstract class Model { + //#model + public static class Author { + public final String handle; + + public Author(String handle) { + this.handle = handle; + } + + // ... + + //#model + + @Override + public String toString() { + return "Author(" + handle + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Author author = (Author) o; + + if (handle != null ? !handle.equals(author.handle) : author.handle != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return handle != null ? handle.hashCode() : 0; + } + //#model + } + //#model + + //#model + + public static class Hashtag { + public final String name; + + public Hashtag(String name) { + this.name = name; + } + + // ... + //#model + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Hashtag other = (Hashtag) obj; + return name.equals(other.name); + } + + @Override + public String toString() { + return "Hashtag(" + name + ")"; + } + //#model + } + //#model + + //#model + + public static class Tweet { + public final Author author; + public final long timestamp; + public final String body; + + public Tweet(Author author, long timestamp, String body) { + this.author = author; + this.timestamp = timestamp; + this.body = body; + } + + public Set hashtags() { + return Arrays.asList(body.split(" ")).stream() + .filter(a -> a.startsWith("#")) + .map(a -> new Hashtag(a)) + .collect(Collectors.toSet()); + } + + // ... + //#model + + @Override + public String toString() { + return "Tweet(" + author + "," + timestamp + "," + body + ")"; + } + + //#model + } + //#model + + //#model + + public static final Hashtag AKKA = new Hashtag("#akka"); + //#model + + public static final Source tweets = Source.from( + Arrays.asList(new Tweet[] { + new Tweet(new Author("rolandkuhn"), System.currentTimeMillis(), "#akka rocks!"), + new Tweet(new Author("patriknw"), System.currentTimeMillis(), "#akka !"), + new Tweet(new Author("bantonsson"), System.currentTimeMillis(), "#akka !"), + new Tweet(new Author("drewhk"), System.currentTimeMillis(), "#akka !"), + new Tweet(new Author("ktosopl"), System.currentTimeMillis(), "#akka on the rocks!"), + new Tweet(new Author("mmartynas"), System.currentTimeMillis(), "wow #akka !"), + new Tweet(new Author("akkateam"), System.currentTimeMillis(), "#akka rocks!"), + new Tweet(new Author("bananaman"), System.currentTimeMillis(), "#bananas rock!"), + new Tweet(new Author("appleman"), System.currentTimeMillis(), "#apples rock!"), + new Tweet(new Author("drama"), System.currentTimeMillis(), "we compared #apples to #oranges!") + })); + } + + static abstract class Example0 { + //#tweet-source + Source tweets; + //#tweet-source + } + + static abstract class Example1 { + //#first-sample + //#materializer-setup + final ActorSystem system = ActorSystem.create("reactive-tweets"); + final Materializer mat = ActorMaterializer.create(system); + //#first-sample + //#materializer-setup + } + + static class Example2 { + public void run(final Materializer mat) throws TimeoutException, InterruptedException { + //#backpressure-by-readline + final Future completion = + Source.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + .map(i -> { System.out.println("map => " + i); return i; }) + .runForeach(i -> System.console().readLine("Element = %s continue reading? [press enter]\n", i), mat); + + Await.ready(completion, FiniteDuration.create(1, TimeUnit.MINUTES)); + //#backpressure-by-readline + } + } + + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void demonstrateFilterAndMap() { + final SilenceSystemOut.System System = SilenceSystemOut.get(); + + //#first-sample + + //#authors-filter-map + final Source authors = + tweets + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> t.author); + //#first-sample + //#authors-filter-map + + new Object() { + //#authors-collect + JavaPartialFunction collectFunction = + new JavaPartialFunction() { + public Author apply(Tweet t, boolean isCheck) { + if (t.hashtags().contains(AKKA)) { + if (isCheck) return null; // to spare the expensive or side-effecting code + return t.author; + } else { + throw noMatch(); + } + } + }; + + final Source authors = + tweets.collect(collectFunction); + //#authors-collect + }; + + //#first-sample + + //#authors-foreachsink-println + authors.runWith(Sink.foreach(a -> System.out.println(a)), mat); + //#first-sample + //#authors-foreachsink-println + + //#authors-foreach-println + authors.runForeach(a -> System.out.println(a), mat); + //#authors-foreach-println + } + + @Test + public void demonstrateMapConcat() { + //#hashtags-mapConcat + final Source hashtags = + tweets.mapConcat(t -> new ArrayList(t.hashtags())); + //#hashtags-mapConcat + } + + static abstract class HiddenDefinitions { + //#flow-graph-broadcast + Sink writeAuthors; + Sink writeHashtags; + //#flow-graph-broadcast + } + + @Test + public void demonstrateBroadcast() { + final Sink> writeAuthors = Sink.ignore(); + final Sink> writeHashtags = Sink.ignore(); + + //#flow-graph-broadcast + RunnableGraph.fromGraph(GraphDSL.create(b -> { + final UniformFanOutShape bcast = b.add(Broadcast.create(2)); + final FlowShape toAuthor = + b.add(Flow.of(Tweet.class).map(t -> t.author)); + final FlowShape toTags = + b.add(Flow.of(Tweet.class).mapConcat(t -> new ArrayList(t.hashtags()))); + final SinkShape authors = b.add(writeAuthors); + final SinkShape hashtags = b.add(writeHashtags); + + b.from(b.add(tweets)).viaFanOut(bcast).via(toAuthor).to(authors); + b.from(bcast).via(toTags).to(hashtags); + return ClosedShape.getInstance(); + })).run(mat); + //#flow-graph-broadcast + } + + long slowComputation(Tweet t) { + try { + // act as if performing some heavy computation + Thread.sleep(500); + } catch (InterruptedException e) {} + return 42; + } + + @Test + public void demonstrateSlowProcessing() { + //#tweets-slow-consumption-dropHead + tweets + .buffer(10, OverflowStrategy.dropHead()) + .map(t -> slowComputation(t)) + .runWith(Sink.ignore(), mat); + //#tweets-slow-consumption-dropHead + } + + @Test + public void demonstrateCountOnFiniteStream() { + //#tweets-fold-count + final Sink> sumSink = + Sink.fold(0, (acc, elem) -> acc + elem); + + final RunnableGraph> counter = + tweets.map(t -> 1).toMat(sumSink, Keep.right()); + + final Future sum = counter.run(mat); + + sum.foreach(new Foreach() { + public void each(Integer c) { + System.out.println("Total tweets processed: " + c); + } + }, system.dispatcher()); + //#tweets-fold-count + + new Object() { + //#tweets-fold-count-oneline + final Future sum = tweets.map(t -> 1).runWith(sumSink, mat); + //#tweets-fold-count-oneline + }; + } + + @Test + public void demonstrateMaterializeMultipleTimes() { + final Source tweetsInMinuteFromNow = tweets; // not really in second, just acting as if + + //#tweets-runnable-flow-materialized-twice + final Sink> sumSink = + Sink.fold(0, (acc, elem) -> acc + elem); + final RunnableGraph> counterRunnableGraph = + tweetsInMinuteFromNow + .filter(t -> t.hashtags().contains(AKKA)) + .map(t -> 1) + .toMat(sumSink, Keep.right()); + + // materialize the stream once in the morning + final Future morningTweetsCount = counterRunnableGraph.run(mat); + // and once in the evening, reusing the blueprint + final Future eveningTweetsCount = counterRunnableGraph.run(mat); + //#tweets-runnable-flow-materialized-twice + + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/io/StreamFileDocTest.java b/akka-docs/rst/java/code/docs/stream/io/StreamFileDocTest.java new file mode 100644 index 0000000000..21cdec8adc --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/io/StreamFileDocTest.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream.io; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.IOException; + +import akka.actor.ActorSystem; +import akka.stream.ActorAttributes; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.FileIO; +import docs.stream.SilenceSystemOut; +import docs.stream.cookbook.RecipeParseLines; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Future; +import scala.runtime.BoxedUnit; + +import akka.stream.*; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; + +public class StreamFileDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("StreamFileDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final SilenceSystemOut.System System = SilenceSystemOut.get(); + + { + //#file-source + final File file = new File("example.csv"); + //#file-source + } + + @Test + public void demonstrateMaterializingBytesWritten() throws IOException { + final File file = File.createTempFile(getClass().getName(), ".tmp"); + + try { + //#file-source + Sink> printlnSink = + Sink.foreach(chunk -> System.out.println(chunk.utf8String())); + + Future bytesWritten = + FileIO.fromFile(file) + .to(printlnSink) + .run(mat); + //#file-source + } finally { + file.delete(); + } + } + + @Test + public void demonstrateSettingDispatchersInCode() throws IOException { + final File file = File.createTempFile(getClass().getName(), ".tmp"); + + try { + Sink> byteStringFutureSink = + //#custom-dispatcher-code + FileIO.toFile(file) + .withAttributes(ActorAttributes.dispatcher("custom-blocking-io-dispatcher")); + //#custom-dispatcher-code + } finally { + file.delete(); + } + } + + +} diff --git a/akka-docs/rst/java/code/docs/stream/io/StreamTcpDocTest.java b/akka-docs/rst/java/code/docs/stream/io/StreamTcpDocTest.java new file mode 100644 index 0000000000..c6f044dd04 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/io/StreamTcpDocTest.java @@ -0,0 +1,184 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream.io; + +import java.util.concurrent.ConcurrentLinkedQueue; + +import akka.stream.io.Framing; +import docs.stream.SilenceSystemOut; +import java.net.InetSocketAddress; + +import docs.util.SocketUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Future; +import scala.runtime.BoxedUnit; + +import akka.actor.ActorSystem; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.javadsl.Tcp.*; +import akka.stream.stage.*; +import akka.testkit.JavaTestKit; +import akka.testkit.TestProbe; +import akka.util.ByteString; + +public class StreamTcpDocTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("StreamTcpDocTest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final SilenceSystemOut.System System = SilenceSystemOut.get(); + + private final ConcurrentLinkedQueue input = new ConcurrentLinkedQueue(); + { + input.add("Hello world"); + input.add("What a lovely day"); + } + + private String readLine(String prompt) { + String s = input.poll(); + return (s == null ? "q": s); + } + + @Test + public void demonstrateSimpleServerConnection() { + { + //#echo-server-simple-bind + // IncomingConnection and ServerBinding imported from Tcp + final Source> connections = + Tcp.get(system).bind("127.0.0.1", 8889); + //#echo-server-simple-bind + } + { + + final InetSocketAddress localhost = SocketUtils.temporaryServerAddress(); + final Source> connections = + Tcp.get(system).bind(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7 + + //#echo-server-simple-handle + connections.runForeach(connection -> { + System.out.println("New connection from: " + connection.remoteAddress()); + + final Flow echo = Flow.of(ByteString.class) + .via(Framing.delimiter(ByteString.fromString("\n"), 256, false)) + .map(bytes -> bytes.utf8String()) + .map(s -> s + "!!!\n") + .map(s -> ByteString.fromString(s)); + + connection.handleWith(echo, mat); + }, mat); + //#echo-server-simple-handle + } + } + + @Test + public void actuallyWorkingClientServerApp() { + + final InetSocketAddress localhost = SocketUtils.temporaryServerAddress(); + + final TestProbe serverProbe = new TestProbe(system); + + final Source> connections = + Tcp.get(system).bind(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7 + //#welcome-banner-chat-server + connections.runForeach(connection -> { + // server logic, parses incoming commands + final PushStage commandParser = new PushStage() { + @Override public SyncDirective onPush(String elem, Context ctx) { + if (elem.equals("BYE")) + return ctx.finish(); + else + return ctx.push(elem + "!"); + } + }; + + final String welcomeMsg = "Welcome to: " + connection.localAddress() + + " you are: " + connection.remoteAddress() + "!\n"; + + final Source welcome = + Source.single(ByteString.fromString(welcomeMsg)); + final Flow echoFlow = + Flow.of(ByteString.class) + .via(Framing.delimiter(ByteString.fromString("\n"), 256, false)) + .map(bytes -> bytes.utf8String()) + //#welcome-banner-chat-server + .map(command -> { + serverProbe.ref().tell(command, null); + return command; + }) + //#welcome-banner-chat-server + .transform(() -> commandParser) + .map(s -> s + "\n") + .map(s -> ByteString.fromString(s)); + + final Flow serverLogic = + Flow.fromGraph(GraphDSL.create(builder -> { + final UniformFanInShape concat = + builder.add(Concat.create()); + final FlowShape echo = builder.add(echoFlow); + + builder + .from(builder.add(welcome)).toFanIn(concat) + .from(echo).toFanIn(concat); + + return FlowShape.of(echo.in(), concat.out()); + })); + + connection.handleWith(serverLogic, mat); + }, mat); + + //#welcome-banner-chat-server + + { + //#repl-client + final Flow> connection = + Tcp.get(system).outgoingConnection("127.0.0.1", 8889); + //#repl-client + } + + { + final Flow> connection = + Tcp.get(system).outgoingConnection(localhost.getHostName(), localhost.getPort()); // TODO getHostString in Java7 + //#repl-client + + final PushStage replParser = new PushStage() { + @Override public SyncDirective onPush(String elem, Context ctx) { + if (elem.equals("q")) + return ctx.pushAndFinish(ByteString.fromString("BYE\n")); + else + return ctx.push(ByteString.fromString(elem + "\n")); + } + }; + + final Flow repl = Flow.of(ByteString.class) + .via(Framing.delimiter(ByteString.fromString("\n"), 256, false)) + .map(bytes -> bytes.utf8String()) + .map(text -> {System.out.println("Server: " + text); return "next";}) + .map(elem -> readLine("> ")) + .transform(() -> replParser); + + connection.join(repl).run(mat); + //#repl-client + } + + serverProbe.expectMsg("Hello world"); + serverProbe.expectMsg("What a lovely day"); + serverProbe.expectMsg("BYE"); + } + +} \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeByteStrings.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeByteStrings.java new file mode 100644 index 0000000000..d4aff27dcd --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeByteStrings.java @@ -0,0 +1,207 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.stream.stage.Context; +import akka.stream.stage.PushPullStage; +import akka.stream.stage.PushStage; +import akka.stream.stage.SyncDirective; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.Tuple2; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class RecipeByteStrings extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeByteStrings"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + final Source rawBytes = Source.from(Arrays.asList( + ByteString.fromArray(new byte[] { 1, 2 }), + ByteString.fromArray(new byte[] { 3 }), + ByteString.fromArray(new byte[] { 4, 5, 6 }), + ByteString.fromArray(new byte[] { 7, 8, 9 }))); + + @Test + public void chunker() throws Exception { + new JavaTestKit(system) { + final int CHUNK_LIMIT = 2; + + //#bytestring-chunker + class Chunker extends PushPullStage { + private final int chunkSize; + private ByteString buffer = ByteString.empty(); + + public Chunker(int chunkSize) { + this.chunkSize = chunkSize; + } + + @Override + public SyncDirective onPush(ByteString elem, Context ctx) { + buffer = buffer.concat(elem); + return emitChunkOrPull(ctx); + } + + @Override + public SyncDirective onPull(Context ctx) { + return emitChunkOrPull(ctx); + } + + public SyncDirective emitChunkOrPull(Context ctx) { + if (buffer.isEmpty()) { + return ctx.pull(); + } else { + Tuple2 split = buffer.splitAt(chunkSize); + ByteString emit = split._1(); + buffer = split._2(); + return ctx.push(emit); + } + } + } + //#bytestring-chunker + + { + //#bytestring-chunker2 + Source chunksStream = + rawBytes.transform(() -> new Chunker(CHUNK_LIMIT)); + //#bytestring-chunker2 + + Future> chunksFuture = chunksStream.grouped(10).runWith(Sink.head(), mat); + + List chunks = Await.result(chunksFuture, FiniteDuration.create(3, TimeUnit.SECONDS)); + + for (ByteString chunk : chunks) { + assertTrue(chunk.size() <= 2); + } + + ByteString sum = ByteString.empty(); + for (ByteString chunk : chunks) { + sum = sum.concat(chunk); + } + assertEquals(sum, ByteString.fromArray(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })); + } + + }; + } + + @Test + public void limiterShouldWork() throws Exception { + new JavaTestKit(system) { + final int SIZE_LIMIT = 9; + + //#bytes-limiter + class ByteLimiter extends PushStage { + final long maximumBytes; + private int count = 0; + + public ByteLimiter(long maximumBytes) { + this.maximumBytes = maximumBytes; + } + + @Override + public SyncDirective onPush(ByteString chunk, Context ctx) { + count += chunk.size(); + if (count > maximumBytes) { + return ctx.fail(new IllegalStateException("Too much bytes")); + } else { + return ctx.push(chunk); + } + } + } + //#bytes-limiter + + { + //#bytes-limiter2 + Flow limiter = + Flow.of(ByteString.class).transform(() -> new ByteLimiter(SIZE_LIMIT)); + //#bytes-limiter2 + + final Source bytes1 = Source.from(Arrays.asList( + ByteString.fromArray(new byte[] { 1, 2 }), + ByteString.fromArray(new byte[] { 3 }), + ByteString.fromArray(new byte[] { 4, 5, 6 }), + ByteString.fromArray(new byte[] { 7, 8, 9 }))); + + final Source bytes2 = Source.from(Arrays.asList( + ByteString.fromArray(new byte[] { 1, 2 }), + ByteString.fromArray(new byte[] { 3 }), + ByteString.fromArray(new byte[] { 4, 5, 6 }), + ByteString.fromArray(new byte[] { 7, 8, 9, 10 }))); + + FiniteDuration threeSeconds = FiniteDuration.create(3, TimeUnit.SECONDS); + + List got = Await.result(bytes1.via(limiter).grouped(10).runWith(Sink.head(), mat), threeSeconds); + ByteString acc = ByteString.empty(); + for (ByteString b : got) { + acc = acc.concat(b); + } + assertEquals(acc, ByteString.fromArray(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })); + + boolean thrown = false; + try { + Await.result(bytes2.via(limiter).grouped(10).runWith(Sink.head(), mat), threeSeconds); + } catch (IllegalStateException ex) { + thrown = true; + } + + assertTrue("Expected IllegalStateException to be thrown", thrown); + } + }; + } + + @Test + public void compacting() throws Exception { + new JavaTestKit(system) { + { + final Source rawBytes = Source.from(Arrays.asList( + ByteString.fromArray(new byte[] { 1, 2 }), + ByteString.fromArray(new byte[] { 3 }), + ByteString.fromArray(new byte[] { 4, 5, 6 }), + ByteString.fromArray(new byte[] { 7, 8, 9 }))); + + //#compacting-bytestrings + Source compacted = rawBytes.map(bs -> bs.compact()); + //#compacting-bytestrings + + FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS); + List got = Await.result(compacted.grouped(10).runWith(Sink.head(), mat), timeout); + + for (ByteString byteString : got) { + assertTrue(byteString.isCompact()); + } + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDigest.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDigest.java new file mode 100644 index 0000000000..5d835d3da4 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDigest.java @@ -0,0 +1,105 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.stream.stage.Context; +import akka.stream.stage.PushPullStage; +import akka.stream.stage.SyncDirective; +import akka.stream.stage.TerminationDirective; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; + +public class RecipeDigest extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeDigest"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + //#calculating-digest + public PushPullStage digestCalculator(String algorithm) + throws NoSuchAlgorithmException { + return new PushPullStage() { + final MessageDigest digest = MessageDigest.getInstance(algorithm); + + @Override + public SyncDirective onPush(ByteString chunk, Context ctx) { + digest.update(chunk.toArray()); + return ctx.pull(); + } + + @Override + public SyncDirective onPull(Context ctx) { + if (ctx.isFinishing()) { + return ctx.pushAndFinish(ByteString.fromArray(digest.digest())); + } else { + return ctx.pull(); + } + } + + @Override + public TerminationDirective onUpstreamFinish(Context ctx) { + // If the stream is finished, we need to emit the last element in the onPull block. + // It is not allowed to directly emit elements from a termination block + // (onUpstreamFinish or onUpstreamFailure) + return ctx.absorbTermination(); + } + }; + } + //#calculating-digest + + { + Source data = Source.from(Arrays.asList( + ByteString.fromString("abcdbcdecdef"), + ByteString.fromString("defgefghfghighijhijkijkljklmklmnlmnomnopnopq"))); + + //#calculating-digest2 + final Source digest = data + .transform(() -> digestCalculator("SHA-256")); + //#calculating-digest2 + + ByteString got = Await.result(digest.runWith(Sink.head(), mat), Duration.create(3, TimeUnit.SECONDS)); + assertEquals(ByteString.fromInts( + 0x24, 0x8d, 0x6a, 0x61, + 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, + 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, + 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, + 0x19, 0xdb, 0x06, 0xc1), got); + } + }; + } +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java new file mode 100644 index 0000000000..37b81e845d --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java @@ -0,0 +1,75 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Future; +import scala.runtime.BoxedUnit; + +import java.util.ArrayList; +import java.util.List; + +public class RecipeDroppyBroadcast extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeLoggingElements"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + //#droppy-bcast + // Makes a sink drop elements if too slow + public Sink> droppySink(Sink> sink, int size) { + return Flow. create() + .buffer(size, OverflowStrategy.dropHead()) + .toMat(sink, Keep.right()); + } + //#droppy-bcast + + { + final List nums = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + nums.add(i + 1); + } + + final Sink> mySink1 = Sink.ignore(); + final Sink> mySink2 = Sink.ignore(); + final Sink> mySink3 = Sink.ignore(); + + final Source myData = Source.from(nums); + + //#droppy-bcast2 + RunnableGraph.fromGraph(GraphDSL.create(builder -> { + final int outputCount = 3; + final UniformFanOutShape bcast = + builder.add(Broadcast.create(outputCount)); + builder.from(builder.add(myData)).toFanOut(bcast); + builder.from(bcast).to(builder.add(droppySink(mySink1, 10))); + builder.from(bcast).to(builder.add(droppySink(mySink2, 10))); + builder.from(bcast).to(builder.add(droppySink(mySink3, 10))); + return ClosedShape.getInstance(); + })); + //#droppy-bcast2 + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeFlattenList.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeFlattenList.java new file mode 100644 index 0000000000..9fcd58cccd --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeFlattenList.java @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; + +public class RecipeFlattenList extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeFlattenList"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void workWithMapConcat() throws Exception { + new JavaTestKit(system) { + { + Source, BoxedUnit> someDataSource = Source + .from(Arrays.asList(Arrays.asList(new Message("1")), Arrays.asList(new Message("2"), new Message("3")))); + + //#flattening-lists + Source, BoxedUnit> myData = someDataSource; + Source flattened = myData.mapConcat(i -> i); + //#flattening-lists + + List got = Await.result(flattened.grouped(10).runWith(Sink.head(), mat), + new FiniteDuration(1, TimeUnit.SECONDS)); + assertEquals(got.get(0), new Message("1")); + assertEquals(got.get(1), new Message("2")); + assertEquals(got.get(2), new Message("3")); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java new file mode 100644 index 0000000000..02309fa33e --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java @@ -0,0 +1,236 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.*; +import akka.dispatch.Mapper; +import akka.japi.pf.ReceiveBuilder; +import akka.pattern.Patterns; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.testkit.JavaTestKit; +import akka.util.Timeout; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.PartialFunction; +import scala.concurrent.Future; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static junit.framework.TestCase.assertTrue; + +public class RecipeGlobalRateLimit extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeGlobalRateLimit"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + static + //#global-limiter-actor + public class Limiter extends AbstractActor { + + public static class WantToPass {} + public static final WantToPass WANT_TO_PASS = new WantToPass(); + + public static class MayPass {} + public static final MayPass MAY_PASS = new MayPass(); + + public static class ReplenishTokens {} + public static final ReplenishTokens REPLENISH_TOKENS = new ReplenishTokens(); + + private final int maxAvailableTokens; + private final FiniteDuration tokenRefreshPeriod; + private final int tokenRefreshAmount; + + private final List waitQueue = new ArrayList<>(); + private final Cancellable replenishTimer; + + private int permitTokens; + + public static Props props(int maxAvailableTokens, FiniteDuration tokenRefreshPeriod, + int tokenRefreshAmount) { + return Props.create(Limiter.class, maxAvailableTokens, tokenRefreshPeriod, + tokenRefreshAmount); + } + + private Limiter(int maxAvailableTokens, FiniteDuration tokenRefreshPeriod, + int tokenRefreshAmount) { + this.maxAvailableTokens = maxAvailableTokens; + this.tokenRefreshPeriod = tokenRefreshPeriod; + this.tokenRefreshAmount = tokenRefreshAmount; + this.permitTokens = maxAvailableTokens; + + this.replenishTimer = system.scheduler().schedule( + this.tokenRefreshPeriod, + this.tokenRefreshPeriod, + self(), + REPLENISH_TOKENS, + context().system().dispatcher(), + self()); + + receive(open()); + } + + PartialFunction open() { + return ReceiveBuilder + .match(ReplenishTokens.class, rt -> { + permitTokens = Math.min(permitTokens + tokenRefreshAmount, maxAvailableTokens); + }) + .match(WantToPass.class, wtp -> { + permitTokens -= 1; + sender().tell(MAY_PASS, self()); + if (permitTokens == 0) { + context().become(closed()); + } + }).build(); + } + + PartialFunction closed() { + return ReceiveBuilder + .match(ReplenishTokens.class, rt -> { + permitTokens = Math.min(permitTokens + tokenRefreshAmount, maxAvailableTokens); + releaseWaiting(); + }) + .match(WantToPass.class, wtp -> { + waitQueue.add(sender()); + }) + .build(); + } + + private void releaseWaiting() { + final List toBeReleased = new ArrayList<>(permitTokens); + for (int i = 0; i < permitTokens && i < waitQueue.size(); i++) { + toBeReleased.add(waitQueue.remove(i)); + } + + permitTokens -= toBeReleased.size(); + toBeReleased.stream().forEach(ref -> ref.tell(MAY_PASS, self())); + if (permitTokens > 0) { + context().become(open()); + } + } + + @Override + public void postStop() { + replenishTimer.cancel(); + waitQueue.stream().forEach(ref -> { + ref.tell(new Status.Failure(new IllegalStateException("limiter stopped")), self()); + }); + } + } + //#global-limiter-actor + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + //#global-limiter-flow + public Flow limitGlobal(ActorRef limiter, FiniteDuration maxAllowedWait) { + final int parallelism = 4; + final Flow f = Flow.create(); + + return f.mapAsync(parallelism, element -> { + final Timeout triggerTimeout = new Timeout(maxAllowedWait); + final Future limiterTriggerFuture = + Patterns.ask(limiter, Limiter.WANT_TO_PASS, triggerTimeout); + return limiterTriggerFuture.map(new Mapper() { + @Override + public T apply(Object parameter) { + return element; + } + }, system.dispatcher()); + }); + } + //#global-limiter-flow + + { + // Use a large period and emulate the timer by hand instead + ActorRef limiter = system.actorOf(Limiter.props(2, new FiniteDuration(100, TimeUnit.DAYS), 1), "limiter"); + + final Iterator e1 = new Iterator() { + @Override + public boolean hasNext() { + return true; + } + + @Override + public String next() { + return "E1"; + } + }; + final Iterator e2 = new Iterator() { + @Override + public boolean hasNext() { + return true; + } + + @Override + public String next() { + return "E2"; + } + }; + + final FiniteDuration twoSeconds = Duration.create(2, TimeUnit.SECONDS); + + final Sink> sink = TestSink.probe(system); + final TestSubscriber.Probe probe = + RunnableGraph.>fromGraph( + GraphDSL.create(sink, (builder, s) -> { + final int inputPorts = 2; + final UniformFanInShape merge = builder.add(Merge.create(inputPorts)); + + final SourceShape source1 = + builder.add(Source.fromIterator(() -> e1).via(limitGlobal(limiter, twoSeconds))); + final SourceShape source2 = + builder.add(Source.fromIterator(() -> e2).via(limitGlobal(limiter, twoSeconds))); + + builder.from(source1).toFanIn(merge); + builder.from(source2).toFanIn(merge); + builder.from(merge).to(s); + return ClosedShape.getInstance(); + }) + ).run(mat); + + probe.expectSubscription().request(1000); + + FiniteDuration fiveHundredMillis = FiniteDuration.create(500, TimeUnit.MILLISECONDS); + + assertTrue(probe.expectNext().startsWith("E")); + assertTrue(probe.expectNext().startsWith("E")); + probe.expectNoMsg(fiveHundredMillis); + + limiter.tell(Limiter.REPLENISH_TOKENS, getTestActor()); + assertTrue(probe.expectNext().startsWith("E")); + probe.expectNoMsg(fiveHundredMillis); + + final Set resultSet = new HashSet<>(); + for (int i = 0; i < 100; i++) { + limiter.tell(Limiter.REPLENISH_TOKENS, getTestActor()); + resultSet.add(probe.expectNext()); + } + + assertTrue(resultSet.contains("E1")); + assertTrue(resultSet.contains("E2")); + + probe.expectError(); + } + }; + } +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeHold.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeHold.java new file mode 100644 index 0000000000..b4be817870 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeHold.java @@ -0,0 +1,154 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Keep; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.stream.stage.DetachedContext; +import akka.stream.stage.DetachedStage; +import akka.stream.stage.DownstreamDirective; +import akka.stream.stage.UpstreamDirective; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.stream.testkit.javadsl.TestSource; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.duration.FiniteDuration; + +import java.util.concurrent.TimeUnit; + +public class RecipeHold extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeMultiGroupBy"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + //#hold-version-1 + class HoldWithInitial extends DetachedStage { + private T currentValue; + + public HoldWithInitial(T initial) { + currentValue = initial; + } + + @Override + public UpstreamDirective onPush(T elem, DetachedContext ctx) { + currentValue = elem; + return ctx.pull(); + } + + @Override + public DownstreamDirective onPull(DetachedContext ctx) { + return ctx.push(currentValue); + } + } + //#hold-version-1 + + //#hold-version-2 + class HoldWithWait extends DetachedStage { + private T currentValue = null; + private boolean waitingFirstValue = true; + + @Override + public UpstreamDirective onPush(T elem, DetachedContext ctx) { + currentValue = elem; + waitingFirstValue = false; + if (ctx.isHoldingDownstream()) { + return ctx.pushAndPull(currentValue); + } else { + return ctx.pull(); + } + } + + @Override + public DownstreamDirective onPull(DetachedContext ctx) { + if (waitingFirstValue) { + return ctx.holdDownstream(); + } else { + return ctx.push(currentValue); + } + } + } + //#hold-version-2 + + @Test + public void workForVersion1() throws Exception { + new JavaTestKit(system) { + { + final Source> source = TestSource.probe(system); + final Sink> sink = TestSink.probe(system); + + Pair, TestSubscriber.Probe> pubSub = + source.transform(() -> new HoldWithInitial<>(0)).toMat(sink, Keep.both()).run(mat); + TestPublisher.Probe pub = pubSub.first(); + TestSubscriber.Probe sub = pubSub.second(); + + sub.requestNext(0); + sub.requestNext(0); + + pub.sendNext(1); + pub.sendNext(2); + + sub.request(2); + sub.expectNext(2, 2); + + pub.sendComplete(); + sub.request(1); + sub.expectComplete(); + } + }; + } + + @Test + public void workForVersion2() throws Exception { + new JavaTestKit(system) { + { + final Source> source = TestSource.probe(system); + final Sink> sink = TestSink.probe(system); + + Pair, TestSubscriber.Probe> pubSub = + source.transform(() -> new HoldWithWait<>()).toMat(sink, Keep.both()).run(mat); + TestPublisher.Probe pub = pubSub.first(); + TestSubscriber.Probe sub = pubSub.second(); + + FiniteDuration timeout = FiniteDuration.create(200, TimeUnit.MILLISECONDS); + + sub.request(1); + sub.expectNoMsg(timeout); + + pub.sendNext(1); + sub.expectNext(1); + + pub.sendNext(2); + pub.sendNext(3); + + sub.request(2); + sub.expectNext(3, 3); + + pub.sendComplete(); + sub.request(1); + sub.expectComplete(); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeKeepAlive.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeKeepAlive.java new file mode 100644 index 0000000000..535b66f830 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeKeepAlive.java @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.runtime.BoxedUnit; + +import java.util.concurrent.TimeUnit; + +public class RecipeKeepAlive extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeKeepAlive"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + class Tick {} + public final Tick TICK = new Tick(); + + @Test + public void workForVersion1() throws Exception { + new JavaTestKit(system) { + { + final ByteString keepAliveMessage = ByteString.fromArray(new byte[]{11}); + + //@formatter:off + //#inject-keepalive + Flow keepAliveInject = + Flow.of(ByteString.class).keepAlive( + scala.concurrent.duration.Duration.create(1, TimeUnit.SECONDS), + () -> keepAliveMessage); + //#inject-keepalive + //@formatter:on + + // Enough to compile, tested elsewhere as a built-in stage + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java new file mode 100644 index 0000000000..e361a6614e --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import akka.stream.ActorMaterializer; +import akka.stream.Attributes; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.DebugFilter; +import akka.testkit.JavaTestKit; +import com.typesafe.config.ConfigFactory; +import docs.stream.SilenceSystemOut; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.runtime.AbstractFunction0; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; + +public class RecipeLoggingElements extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeLoggingElements", ConfigFactory.parseString("akka.loglevel=DEBUG\nakka.loggers = [akka.testkit.TestEventListener]")); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void workWithPrintln() throws Exception { + new JavaTestKit(system) { + final SilenceSystemOut.System System = SilenceSystemOut.get(getTestActor()); + + { + final Source mySource = Source.from(Arrays.asList("1", "2", "3")); + + //#println-debug + mySource.map(elem -> { + System.out.println(elem); + return elem; + }); + //#println-debug + } + }; + } + + @Test + public void workWithLog() throws Exception { + new JavaTestKit(system) { + private T analyse(T i) { + return i; + } + + { + final Source mySource = Source.from(Arrays.asList("1", "2", "3")); + + final int onElement = Logging.WarningLevel(); + final int onFinish = Logging.ErrorLevel(); + final int onFailure = Logging.ErrorLevel(); + + //#log-custom + // customise log levels + mySource.log("before-map") + .withAttributes(Attributes.createLogLevels(onElement, onFinish, onFailure)) + .map(i -> analyse(i)); + + // or provide custom logging adapter + final LoggingAdapter adapter = Logging.getLogger(system, "customLogger"); + mySource.log("custom", adapter); + //#log-custom + + new DebugFilter("customLogger", "[custom] Element: ", false, false, 3).intercept(new AbstractFunction0 () { + public Void apply() { + mySource.log("custom", adapter).runWith(Sink.ignore(), mat); + return null; + } + }, system); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java new file mode 100644 index 0000000000..ef43650012 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java @@ -0,0 +1,153 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.stream.testkit.javadsl.TestSource; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.duration.FiniteDuration; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +public class RecipeManualTrigger extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeKeepAlive"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + class Trigger { + } + + public final Trigger TRIGGER = new Trigger(); + + @Test + public void zipped() throws Exception { + new JavaTestKit(system) { + { + final Source> triggerSource = TestSource.probe(system); + final Sink> messageSink = TestSink.probe(system); + + //#manually-triggered-stream + final RunnableGraph, TestSubscriber.Probe>> g = + RunnableGraph., TestSubscriber.Probe>>fromGraph( + GraphDSL.create( + triggerSource, + messageSink, + (p, s) -> new Pair<>(p, s), + (builder, source, sink) -> { + SourceShape elements = + builder.add(Source.from(Arrays.asList("1", "2", "3", "4")).map(t -> new Message(t))); + FlowShape, Message> takeMessage = + builder.add(Flow.>create().map(p -> p.first())); + final FanInShape2> zip = + builder.add(Zip.create()); + builder.from(elements).toInlet(zip.in0()); + builder.from(source).toInlet(zip.in1()); + builder.from(zip.out()).via(takeMessage).to(sink); + return ClosedShape.getInstance(); + } + ) + ); + //#manually-triggered-stream + + Pair, TestSubscriber.Probe> pubSub = g.run(mat); + TestPublisher.Probe pub = pubSub.first(); + TestSubscriber.Probe sub = pubSub.second(); + + FiniteDuration timeout = FiniteDuration.create(100, TimeUnit.MILLISECONDS); + sub.expectSubscription().request(1000); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + sub.expectNext(new Message("1")); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + pub.sendNext(TRIGGER); + sub.expectNext(new Message("2")); + sub.expectNext(new Message("3")); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + sub.expectNext(new Message("4")); + sub.expectComplete(); + } + }; + } + + @Test + public void zipWith() throws Exception { + new JavaTestKit(system) { + { + final Source> triggerSource = TestSource.probe(system); + final Sink> messageSink = TestSink.probe(system); + + //#manually-triggered-stream-zipwith + final RunnableGraph, TestSubscriber.Probe>> g = + RunnableGraph., TestSubscriber.Probe>>fromGraph( + GraphDSL.create( + triggerSource, + messageSink, + (p, s) -> new Pair<>(p, s), + (builder, source, sink) -> { + final SourceShape elements = + builder.add(Source.from(Arrays.asList("1", "2", "3", "4")).map(t -> new Message(t))); + final FanInShape2 zipWith = + builder.add(ZipWith.create((msg, trigger) -> msg)); + builder.from(elements).toInlet(zipWith.in0()); + builder.from(source).toInlet(zipWith.in1()); + builder.from(zipWith.out()).to(sink); + return ClosedShape.getInstance(); + } + ) + ); + //#manually-triggered-stream-zipwith + + Pair, TestSubscriber.Probe> pubSub = g.run(mat); + TestPublisher.Probe pub = pubSub.first(); + TestSubscriber.Probe sub = pubSub.second(); + + FiniteDuration timeout = FiniteDuration.create(100, TimeUnit.MILLISECONDS); + sub.expectSubscription().request(1000); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + sub.expectNext(new Message("1")); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + pub.sendNext(TRIGGER); + sub.expectNext(new Message("2")); + sub.expectNext(new Message("3")); + sub.expectNoMsg(timeout); + + pub.sendNext(TRIGGER); + sub.expectNext(new Message("4")); + sub.expectComplete(); + + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMissedTicks.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMissedTicks.java new file mode 100644 index 0000000000..976c542bcb --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMissedTicks.java @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Keep; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.stream.testkit.javadsl.TestSource; +import akka.testkit.JavaTestKit; +import akka.testkit.TestLatch; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.duration.Duration; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.concurrent.TimeUnit; + +public class RecipeMissedTicks extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeMultiGroupBy"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + class Tick { + } + + final Tick Tick = new Tick(); + + { + final Source> tickStream = TestSource.probe(system); + final Sink> sink = TestSink.probe(system); + + @SuppressWarnings("unused") + //#missed-ticks + final Flow missedTicks = + Flow.of(Tick.class).conflate(tick -> 0, (missed, tick) -> missed + 1); + //#missed-ticks + final TestLatch latch = new TestLatch(3, system); + final Flow realMissedTicks = + Flow.of(Tick.class).conflate(tick -> 0, (missed, tick) -> { latch.countDown(); return missed + 1; }); + + Pair, TestSubscriber.Probe> pubSub = + tickStream.via(realMissedTicks).toMat(sink, Keep.both()).run(mat); + TestPublisher.Probe pub = pubSub.first(); + TestSubscriber.Probe sub = pubSub.second(); + + pub.sendNext(Tick); + pub.sendNext(Tick); + pub.sendNext(Tick); + pub.sendNext(Tick); + + FiniteDuration timeout = FiniteDuration.create(200, TimeUnit.MILLISECONDS); + + Await.ready(latch, Duration.create(1, TimeUnit.SECONDS)); + + sub.request(1); + sub.expectNext(3); + sub.request(1); + sub.expectNoMsg(timeout); + + pub.sendNext(Tick); + sub.expectNext(0); + + pub.sendComplete(); + sub.request(1); + sub.expectComplete(); + + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMultiGroupByTest.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMultiGroupByTest.java new file mode 100644 index 0000000000..431b6bffdf --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeMultiGroupByTest.java @@ -0,0 +1,154 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Function; +import akka.japi.Pair; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.stream.javadsl.SubSource; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static java.util.stream.Collectors.toList; +import static junit.framework.TestCase.assertTrue; + +public class RecipeMultiGroupByTest extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeMultiGroupBy"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + static class Topic { + private final String name; + + public Topic(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Topic topic = (Topic) o; + + if (name != null ? !name.equals(topic.name) : topic.name != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + } + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + final List extractTopics(Message m) { + final List topics = new ArrayList<>(2); + + if (m.msg.startsWith("1")) { + topics.add(new Topic("1")); + } else { + topics.add(new Topic("1")); + topics.add(new Topic("2")); + } + + return topics; + } + + { + + final Source elems = Source + .from(Arrays.asList("1: a", "1: b", "all: c", "all: d", "1: e")) + .map(s -> new Message(s)); + + //#multi-groupby + final Function> topicMapper = m -> extractTopics(m); + + final Source, BoxedUnit> messageAndTopic = elems + .mapConcat((Message msg) -> { + List topicsForMessage = topicMapper.apply(msg); + // Create a (Msg, Topic) pair for each of the topics + + // the message belongs to + return topicsForMessage + .stream() + .map(topic -> new Pair(msg, topic)) + .collect(toList()); + }); + + SubSource, BoxedUnit> multiGroups = messageAndTopic + .groupBy(2, pair -> pair.second()) + .map(pair -> { + Message message = pair.first(); + Topic topic = pair.second(); + + // do what needs to be done + //#multi-groupby + return pair; + //#multi-groupby + }); + //#multi-groupby + + Future> result = multiGroups + .grouped(10) + .mergeSubstreams() + .map(pair -> { + Topic topic = pair.get(0).second(); + return topic.name + mkString(pair.stream().map(p -> p.first().msg).collect(toList()), "[", ", ", "]"); + }) + .grouped(10) + .runWith(Sink.head(), mat); + + List got = Await.result(result, FiniteDuration.create(3, TimeUnit.SECONDS)); + assertTrue(got.contains("1[1: a, 1: b, all: c, all: d, 1: e]")); + assertTrue(got.contains("2[all: c, all: d]")); + } + }; + } + + public static final String mkString(List l, String start, String separate, String end) { + StringBuilder sb = new StringBuilder(start); + for (String s : l) { + sb.append(s).append(separate); + } + return sb + .delete(sb.length() - separate.length(), sb.length()) + .append(end).toString(); + } +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeParseLines.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeParseLines.java new file mode 100644 index 0000000000..d1684dd93c --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeParseLines.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.io.Framing; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import akka.util.ByteString; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +public class RecipeParseLines extends RecipeTest { + + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeLoggingElements"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void parseLines() throws Exception { + final Source rawData = Source.from(Arrays.asList( + ByteString.fromString("Hello World"), + ByteString.fromString("\r"), + ByteString.fromString("!\r"), + ByteString.fromString("\nHello Akka!\r\nHello Streams!"), + ByteString.fromString("\r\n\r\n"))); + + //#parse-lines + final Source lines = rawData + .via(Framing.delimiter(ByteString.fromString("\r\n"), 100, true)) + .map(b -> b.utf8String()); + //#parse-lines + + Await.result(lines.grouped(10).runWith(Sink.head(), mat), new FiniteDuration(1, TimeUnit.SECONDS)); + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java new file mode 100644 index 0000000000..65459c9f75 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.japi.function.Function; +import akka.japi.function.Function2; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class RecipeReduceByKeyTest extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeLoggingElements"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + { + final Source words = Source.from(Arrays.asList("hello", "world", "and", "hello", "akka")); + + //#word-count + final int MAXIMUM_DISTINCT_WORDS = 1000; + + final Source, BoxedUnit> counts = words + // split the words into separate streams first + .groupBy(MAXIMUM_DISTINCT_WORDS, i -> i) + // add counting logic to the streams + .fold(new Pair<>("", 0), (pair, elem) -> new Pair<>(elem, pair.second() + 1)) + // get a stream of word counts + .mergeSubstreams(); + //#word-count + + final Future>> f = counts.grouped(10).runWith(Sink.head(), mat); + final Set> result = Await.result(f, getRemainingTime()).stream().collect(Collectors.toSet()); + final Set> expected = new HashSet<>(); + expected.add(new Pair<>("hello", 2)); + expected.add(new Pair<>("world", 1)); + expected.add(new Pair<>("and", 1)); + expected.add(new Pair<>("akka", 1)); + Assert.assertEquals(expected, result); + } + }; + } + + //#reduce-by-key-general + static public Flow, BoxedUnit> reduceByKey( + int maximumGroupSize, + Function groupKey, + Function foldZero, + Function2 fold, + Materializer mat) { + + return Flow. create() + .groupBy(maximumGroupSize, i -> i) + .fold((Pair) null, (pair, elem) -> { + final K key = groupKey.apply(elem); + if (pair == null) return new Pair<>(key, fold.apply(foldZero.apply(key), elem)); + else return new Pair<>(key, fold.apply(pair.second(), elem)); + }) + .mergeSubstreams(); + } + //#reduce-by-key-general + + @Test + public void workGeneralised() throws Exception { + new JavaTestKit(system) { + { + final Source words = Source.from(Arrays.asList("hello", "world", "and", "hello", "akka")); + + //#reduce-by-key-general2 + final int MAXIMUM_DISTINCT_WORDS = 1000; + + Source, BoxedUnit> counts = words.via(reduceByKey( + MAXIMUM_DISTINCT_WORDS, + word -> word, + key -> 0, + (count, elem) -> count + 1, + mat)); + + //#reduce-by-key-general2 + final Future>> f = counts.grouped(10).runWith(Sink.head(), mat); + final Set> result = Await.result(f, getRemainingTime()).stream().collect(Collectors.toSet()); + final Set> expected = new HashSet<>(); + expected.add(new Pair<>("hello", 2)); + expected.add(new Pair<>("world", 1)); + expected.add(new Pair<>("and", 1)); + expected.add(new Pair<>("akka", 1)); + Assert.assertEquals(expected, result); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeSimpleDrop.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeSimpleDrop.java new file mode 100644 index 0000000000..ba10e398dd --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeSimpleDrop.java @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.japi.Pair; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.stream.testkit.TestPublisher; +import akka.stream.testkit.TestSubscriber; +import akka.stream.testkit.javadsl.TestSink; +import akka.stream.testkit.javadsl.TestSource; +import akka.testkit.JavaTestKit; +import akka.testkit.TestLatch; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.duration.Duration; +import scala.runtime.BoxedUnit; + +import java.util.concurrent.TimeUnit; + +public class RecipeSimpleDrop extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeSimpleDrop"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void work() throws Exception { + new JavaTestKit(system) { + { + @SuppressWarnings("unused") + //#simple-drop + final Flow droppyStream = + Flow.of(Message.class).conflate(i -> i, (lastMessage, newMessage) -> newMessage); + //#simple-drop + final TestLatch latch = new TestLatch(2, system); + final Flow realDroppyStream = + Flow.of(Message.class).conflate(i -> i, (lastMessage, newMessage) -> { latch.countDown(); return newMessage; }); + + final Pair, TestSubscriber.Probe> pubSub = TestSource + . probe(system) + .via(realDroppyStream) + .toMat(TestSink.probe(system), + (pub, sub) -> new Pair<>(pub, sub)) + .run(mat); + final TestPublisher.Probe pub = pubSub.first(); + final TestSubscriber.Probe sub = pubSub.second(); + + pub.sendNext(new Message("1")); + pub.sendNext(new Message("2")); + pub.sendNext(new Message("3")); + + Await.ready(latch, Duration.create(1, TimeUnit.SECONDS)); + + sub.requestNext(new Message("3")); + + pub.sendComplete(); + sub.request(1); + sub.expectComplete(); + } + }; + } +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeTest.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeTest.java new file mode 100644 index 0000000000..c4f93a76a3 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeTest.java @@ -0,0 +1,40 @@ +package docs.stream.javadsl.cookbook; + +public class RecipeTest { + final class Message { + public final String msg; + + public Message(String msg) { + this.msg = msg; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Message message = (Message) o; + + if (msg != null ? !msg.equals(message.msg) : message.msg != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return msg != null ? msg.hashCode() : 0; + } + } + + final class Trigger { + } + + final class Job { + } +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeToStrict.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeToStrict.java new file mode 100644 index 0000000000..f4a3d53908 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeToStrict.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class RecipeToStrict extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeLoggingElements"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + @Test + public void workWithPrintln() throws Exception { + new JavaTestKit(system) { + { + final Source myData = Source.from(Arrays.asList("1", "2", "3")); + final int MAX_ALLOWED_SIZE = 100; + + //#draining-to-list + final Future> strings = myData + .grouped(MAX_ALLOWED_SIZE).runWith(Sink.head(), mat); + //#draining-to-list + + Await.result(strings, new FiniteDuration(1, TimeUnit.SECONDS)); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java new file mode 100644 index 0000000000..7d30e65038 --- /dev/null +++ b/akka-docs/rst/java/code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2015 Typesafe + */ +package docs.stream.javadsl.cookbook; + +import akka.actor.ActorSystem; +import akka.stream.*; +import akka.stream.javadsl.*; +import akka.testkit.JavaTestKit; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.BoxedUnit; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertTrue; + +public class RecipeWorkerPool extends RecipeTest { + static ActorSystem system; + + @BeforeClass + public static void setup() { + system = ActorSystem.create("RecipeWorkerPool"); + } + + @AfterClass + public static void tearDown() { + JavaTestKit.shutdownActorSystem(system); + system = null; + } + + final Materializer mat = ActorMaterializer.create(system); + + //#worker-pool + public static Flow balancer( + Flow worker, int workerCount) { + return Flow.fromGraph(GraphDSL.create(b -> { + boolean waitForAllDownstreams = true; + final UniformFanOutShape balance = + b.add(Balance.create(workerCount, waitForAllDownstreams)); + final UniformFanInShape merge = + b.add(Merge.create(workerCount)); + + for (int i = 0; i < workerCount; i++) { + b.from(balance.out(i)).via(b.add(worker)).toInlet(merge.in(i)); + } + + return FlowShape.of(balance.in(), merge.out()); + })); + } + //#worker-pool + + @Test + public void workForVersion1() throws Exception { + new JavaTestKit(system) { + { + Source data = + Source + .from(Arrays.asList("1", "2", "3", "4", "5")) + .map(t -> new Message(t)); + + Flow worker = Flow.of(Message.class).map(m -> new Message(m.msg + " done")); + + //#worker-pool2 + Flow balancer = balancer(worker, 3); + Source processedJobs = data.via(balancer); + //#worker-pool2 + + FiniteDuration timeout = FiniteDuration.create(200, TimeUnit.MILLISECONDS); + Future> future = processedJobs.map(m -> m.msg).grouped(10).runWith(Sink.head(), mat); + List got = Await.result(future, timeout); + assertTrue(got.contains("1 done")); + assertTrue(got.contains("2 done")); + assertTrue(got.contains("3 done")); + assertTrue(got.contains("4 done")); + assertTrue(got.contains("5 done")); + } + }; + } + +} diff --git a/akka-docs/rst/java/code/docs/util/SocketUtils.java b/akka-docs/rst/java/code/docs/util/SocketUtils.java new file mode 100644 index 0000000000..7358a0d34f --- /dev/null +++ b/akka-docs/rst/java/code/docs/util/SocketUtils.java @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.util; + +import java.net.InetSocketAddress; + +import java.io.IOException; +import java.net.ServerSocket; +import java.nio.channels.ServerSocketChannel; + +public class SocketUtils { + + public static InetSocketAddress temporaryServerAddress(String hostname) { + try { + ServerSocket socket = ServerSocketChannel.open().socket(); + socket.bind(new InetSocketAddress(hostname, 0)); + InetSocketAddress address = new InetSocketAddress(hostname, socket.getLocalPort()); + socket.close(); + return address; + } + catch (IOException io) { + throw new RuntimeException(io); + } + } + + public static InetSocketAddress temporaryServerAddress() { + return temporaryServerAddress("127.0.0.1"); + } + +} \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/client-side/connection-level.rst b/akka-docs/rst/java/http/client-side/connection-level.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/connection-level.rst rename to akka-docs/rst/java/http/client-side/connection-level.rst diff --git a/akka-docs-dev/rst/java/http/client-side/host-level.rst b/akka-docs/rst/java/http/client-side/host-level.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/host-level.rst rename to akka-docs/rst/java/http/client-side/host-level.rst diff --git a/akka-docs-dev/rst/java/http/client-side/https-support.rst b/akka-docs/rst/java/http/client-side/https-support.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/https-support.rst rename to akka-docs/rst/java/http/client-side/https-support.rst diff --git a/akka-docs-dev/rst/java/http/client-side/index.rst b/akka-docs/rst/java/http/client-side/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/index.rst rename to akka-docs/rst/java/http/client-side/index.rst diff --git a/akka-docs-dev/rst/java/http/client-side/request-level.rst b/akka-docs/rst/java/http/client-side/request-level.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/request-level.rst rename to akka-docs/rst/java/http/client-side/request-level.rst diff --git a/akka-docs-dev/rst/java/http/client-side/websocket-support.rst b/akka-docs/rst/java/http/client-side/websocket-support.rst similarity index 100% rename from akka-docs-dev/rst/java/http/client-side/websocket-support.rst rename to akka-docs/rst/java/http/client-side/websocket-support.rst diff --git a/akka-docs-dev/rst/java/http/configuration.rst b/akka-docs/rst/java/http/configuration.rst similarity index 100% rename from akka-docs-dev/rst/java/http/configuration.rst rename to akka-docs/rst/java/http/configuration.rst diff --git a/akka-docs-dev/rst/java/http/http-model.rst b/akka-docs/rst/java/http/http-model.rst similarity index 100% rename from akka-docs-dev/rst/java/http/http-model.rst rename to akka-docs/rst/java/http/http-model.rst diff --git a/akka-docs-dev/rst/java/http/index.rst b/akka-docs/rst/java/http/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/index.rst rename to akka-docs/rst/java/http/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/extractHost.rst b/akka-docs/rst/java/http/routing-dsl/directives/host-directives/extractHost.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/extractHost.rst rename to akka-docs/rst/java/http/routing-dsl/directives/host-directives/extractHost.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/host.rst b/akka-docs/rst/java/http/routing-dsl/directives/host-directives/host.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/host.rst rename to akka-docs/rst/java/http/routing-dsl/directives/host-directives/host.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/index.rst b/akka-docs/rst/java/http/routing-dsl/directives/host-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/host-directives/index.rst rename to akka-docs/rst/java/http/routing-dsl/directives/host-directives/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/index.rst b/akka-docs/rst/java/http/routing-dsl/directives/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/index.rst rename to akka-docs/rst/java/http/routing-dsl/directives/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/delete.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/delete.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/delete.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/delete.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/extractMethod.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/extractMethod.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/extractMethod.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/extractMethod.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/get.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/get.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/get.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/get.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/head.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/head.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/head.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/head.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/index.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/index.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/method.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/method.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/method.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/method.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/options.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/options.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/options.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/options.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/patch.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/patch.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/patch.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/patch.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/post.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/post.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/post.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/post.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/put.rst b/akka-docs/rst/java/http/routing-dsl/directives/method-directives/put.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/method-directives/put.rst rename to akka-docs/rst/java/http/routing-dsl/directives/method-directives/put.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/directives/path-directives.rst b/akka-docs/rst/java/http/routing-dsl/directives/path-directives.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/directives/path-directives.rst rename to akka-docs/rst/java/http/routing-dsl/directives/path-directives.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/handlers.rst b/akka-docs/rst/java/http/routing-dsl/handlers.rst similarity index 83% rename from akka-docs-dev/rst/java/http/routing-dsl/handlers.rst rename to akka-docs/rst/java/http/routing-dsl/handlers.rst index 0d51a44ba8..189b289023 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/handlers.rst +++ b/akka-docs/rst/java/http/routing-dsl/handlers.rst @@ -24,7 +24,7 @@ by inspecting the ``RequestContext`` and returning a ``RouteResult``: Such a handler inspects the ``RequestContext`` it receives and uses the ``RequestContext``'s methods to create a response: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: simple-handler The handler can include any kind of logic but must return a ``RouteResult`` in the end which can only @@ -32,7 +32,7 @@ be created by using one of the ``RequestContext`` methods. A handler instance can be used once or several times as shown in the full example: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: simple-handler-example-full Handlers and Request Values @@ -42,14 +42,14 @@ In many cases, instead of manually inspecting the request, a handler will make u to extract details from the request. This is possible using one of the other ``handleWith`` overloads that bind the values of one or more request values with a ``HandlerN`` instance to produce a ``Route``: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: handler2 The handler here implements multiplication of two integers. However, it doesn't need to specify where these parameters come from. In ``handleWith``, as many request values of the matching type have to be specified as the handler needs. This can be seen in the full example: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: handler2-example-full Here, the handler is again being reused. First, in creating a route that expects URI parameters ``x`` and ``y``. This @@ -67,7 +67,7 @@ type represents a sausage, put between the "buns" which are ``RequestContext`` a In Java 8 handlers can be provided as function literals or method references. The previous example can then be written like this: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: handler2-java8-example-full @@ -87,12 +87,12 @@ Providing Handlers by Reflection Using Java before Java 8, writing out handlers as (anonymous) classes can be unwieldy. Therefore, ``handleReflectively`` overloads are provided that allow writing handler as simple methods and specifying them by name: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: reflective The complete calculator example can then be written like this: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: reflective-example-full There are alternative overloads for ``handleReflectively`` that take a ``Class`` instead of an object instance to refer to @@ -110,7 +110,7 @@ above and use ``RequestContext.completeWith`` for completion which takes an ``Fu This is demonstrated in the following example. Consider a asynchronous service defined like this (making use of Java 8 lambdas): -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: async-service-definition Here the calculator runs the actual calculation in the background and only eventually returns the result. The HTTP @@ -119,7 +119,7 @@ above this can be done in two ways. First, you can use ``handleWithAsyncN`` to be able to return a ``Future``: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: async-handler-1 The handler invokes the service and then maps the calculation result to a ``RouteResult`` using ``Future.map`` and @@ -128,7 +128,7 @@ returns the resulting ``Future``. Otherwise, you can also still use ``handleWithN`` and use ``RequestContext.completeWith`` to "convert" a ``Future`` into a ``RouteResult`` as shown here: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: async-handler-2 Using this style, you can decide in your handler if you want to return a direct synchronous result or if you need @@ -138,5 +138,5 @@ Both alternatives will not block and show the same runtime behavior. Here's the complete example: -.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java +.. includecode:: /../../akka-http-tests/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java :include: async-example-full diff --git a/akka-docs-dev/rst/java/http/routing-dsl/index.rst b/akka-docs/rst/java/http/routing-dsl/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/index.rst rename to akka-docs/rst/java/http/routing-dsl/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/json-support.rst b/akka-docs/rst/java/http/routing-dsl/json-support.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/json-support.rst rename to akka-docs/rst/java/http/routing-dsl/json-support.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/marshalling.rst b/akka-docs/rst/java/http/routing-dsl/marshalling.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/marshalling.rst rename to akka-docs/rst/java/http/routing-dsl/marshalling.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/overview.rst b/akka-docs/rst/java/http/routing-dsl/overview.rst similarity index 99% rename from akka-docs-dev/rst/java/http/routing-dsl/overview.rst rename to akka-docs/rst/java/http/routing-dsl/overview.rst index 94f95b496e..663f97d6ad 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/overview.rst +++ b/akka-docs/rst/java/http/routing-dsl/overview.rst @@ -1,4 +1,4 @@ -.. _routing-java: +.. _http-routing-java: Routing DSL Overview ==================== diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst b/akka-docs/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst rename to akka-docs/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst b/akka-docs/rst/java/http/routing-dsl/request-vals/header-request-vals.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst rename to akka-docs/rst/java/http/routing-dsl/request-vals/header-request-vals.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/http-basic-authenticator.rst b/akka-docs/rst/java/http/routing-dsl/request-vals/http-basic-authenticator.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/request-vals/http-basic-authenticator.rst rename to akka-docs/rst/java/http/routing-dsl/request-vals/http-basic-authenticator.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst b/akka-docs/rst/java/http/routing-dsl/request-vals/index.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst rename to akka-docs/rst/java/http/routing-dsl/request-vals/index.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/oauth2-authenticator.rst b/akka-docs/rst/java/http/routing-dsl/request-vals/oauth2-authenticator.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/request-vals/oauth2-authenticator.rst rename to akka-docs/rst/java/http/routing-dsl/request-vals/oauth2-authenticator.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/routes.rst b/akka-docs/rst/java/http/routing-dsl/routes.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/routes.rst rename to akka-docs/rst/java/http/routing-dsl/routes.rst diff --git a/akka-docs-dev/rst/java/http/routing-dsl/testkit.rst b/akka-docs/rst/java/http/routing-dsl/testkit.rst similarity index 100% rename from akka-docs-dev/rst/java/http/routing-dsl/testkit.rst rename to akka-docs/rst/java/http/routing-dsl/testkit.rst diff --git a/akka-docs-dev/rst/java/http/server-side/low-level-server-side-api.rst b/akka-docs/rst/java/http/server-side/low-level-server-side-api.rst similarity index 99% rename from akka-docs-dev/rst/java/http/server-side/low-level-server-side-api.rst rename to akka-docs/rst/java/http/server-side/low-level-server-side-api.rst index b01b763133..6a80290369 100644 --- a/akka-docs-dev/rst/java/http/server-side/low-level-server-side-api.rst +++ b/akka-docs/rst/java/http/server-side/low-level-server-side-api.rst @@ -112,7 +112,7 @@ if HTTP pipelining is enabled where processing of multiple incoming requests may ``handleWithSyncHandler`` or ``handleWithAsyncHandler``, or the ``map`` or ``mapAsync`` stream operators, this requirement will be automatically fulfilled. -See :ref:`routing-java` for a more convenient high-level DSL to create request handlers. +See :ref:`http-routing-java` for a more convenient high-level DSL to create request handlers. Streaming Request/Response Entities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/akka-docs-dev/rst/java/http/server-side/websocket-support.rst b/akka-docs/rst/java/http/server-side/websocket-support.rst similarity index 100% rename from akka-docs-dev/rst/java/http/server-side/websocket-support.rst rename to akka-docs/rst/java/http/server-side/websocket-support.rst diff --git a/akka-docs-dev/rst/java/stream-index.rst b/akka-docs/rst/java/stream/index.rst similarity index 74% rename from akka-docs-dev/rst/java/stream-index.rst rename to akka-docs/rst/java/stream/index.rst index e89dd7422e..be5bc8f854 100644 --- a/akka-docs-dev/rst/java/stream-index.rst +++ b/akka-docs/rst/java/stream/index.rst @@ -8,7 +8,7 @@ Streams stream-introduction stream-quickstart - ../stream-design + ../../general/stream/stream-design stream-flows-and-basics stream-graphs stream-composition @@ -19,7 +19,7 @@ Streams stream-io stream-parallelism stream-testkit - ../stages-overview + ../../general/stream/stages-overview stream-cookbook - ../stream-configuration + ../../general/stream/stream-configuration migration-guide-1.0-2.x-java diff --git a/akka-docs-dev/rst/java/migration-guide-1.0-2.x-java.rst b/akka-docs/rst/java/stream/migration-guide-1.0-2.x-java.rst similarity index 95% rename from akka-docs-dev/rst/java/migration-guide-1.0-2.x-java.rst rename to akka-docs/rst/java/stream/migration-guide-1.0-2.x-java.rst index 31fa3bec0e..a3fe215fc9 100644 --- a/akka-docs-dev/rst/java/migration-guide-1.0-2.x-java.rst +++ b/akka-docs/rst/java/stream/migration-guide-1.0-2.x-java.rst @@ -103,7 +103,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#flow-wrap +.. includecode:: ../code/docs/stream/MigrationsJava.java#flow-wrap and @@ -119,7 +119,7 @@ and Should be replaced by -.. includecode:: code/docs/MigrationsJava.java#bidi-wrap +.. includecode:: ../code/docs/stream/MigrationsJava.java#bidi-wrap Renamed ``inlet()`` and ``outlet()`` to ``in()`` and ``out()`` in ``SourceShape``, ``SinkShape`` and ``FlowShape`` @@ -168,7 +168,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#graph-create +.. includecode:: ../code/docs/stream/MigrationsJava.java#graph-create Methods that create Source, Sink, Flow from Graphs have been removed ==================================================================== @@ -225,7 +225,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#graph-create-2 +.. includecode:: ../code/docs/stream/MigrationsJava.java#graph-create-2 Some graph Builder methods have been removed ============================================ @@ -255,7 +255,7 @@ Update procedure should be replaced by -.. includecode:: code/docs/MigrationsJava.java#graph-builder +.. includecode:: ../code/docs/stream/MigrationsJava.java#graph-builder Source constructor name changes =============================== @@ -309,7 +309,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#source-creators +.. includecode:: ../code/docs/stream/MigrationsJava.java#source-creators Sink constructor name changes ============================= @@ -333,7 +333,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#sink-creators +.. includecode:: ../code/docs/stream/MigrationsJava.java#sink-creators ``Flow.empty()`` have been removed ================================== @@ -353,7 +353,7 @@ Update procedure should be replaced by -.. includecode:: code/docs/MigrationsJava.java#empty-flow +.. includecode:: ../code/docs/stream/MigrationsJava.java#empty-flow ``flatten(FlattenStrategy)`` has been replaced by named counterparts ==================================================================== @@ -376,7 +376,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#flatMapConcat +.. includecode:: ../code/docs/stream/MigrationsJava.java#flatMapConcat `Sink.fanoutPublisher() and Sink.publisher() is now a single method` ==================================================================== @@ -407,7 +407,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#sink-as-publisher +.. includecode:: ../code/docs/stream/MigrationsJava.java#sink-as-publisher FlexiMerge an FlexiRoute has been replaced by GraphStage ======================================================== @@ -460,7 +460,7 @@ Example This is implemented now as -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/MigrationsJava.java#group-flatten +.. includecode:: ../code/docs/stream/MigrationsJava.java#group-flatten Example 2 ^^^^^^^^^ @@ -479,7 +479,7 @@ Example 2 This is implemented now as -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/MigrationsJava.java#group-fold +.. includecode:: ../code/docs/stream/MigrationsJava.java#group-fold Semantic change in ``isHoldingUpstream`` in the DetachedStage DSL ================================================================= @@ -582,7 +582,7 @@ Example should be replaced by: -.. includecode:: code/docs/MigrationsJava.java#raw-query +.. includecode:: ../code/docs/stream/MigrationsJava.java#raw-query And use of query parameters from ``Uri`` that looked like this: @@ -593,7 +593,7 @@ And use of query parameters from ``Uri`` that looked like this: should be replaced by: -.. includecode:: code/docs/MigrationsJava.java#query-param +.. includecode:: ../code/docs/stream/MigrationsJava.java#query-param SynchronousFileSource and SynchronousFileSink ============================================= @@ -629,7 +629,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#file-source-sink +.. includecode:: ../code/docs/stream/MigrationsJava.java#file-source-sink InputStreamSource and OutputStreamSink ====================================== @@ -674,7 +674,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#input-output-stream-source-sink +.. includecode:: ../code/docs/stream/MigrationsJava.java#input-output-stream-source-sink OutputStreamSource and InputStreamSink @@ -712,4 +712,4 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsJava.java#output-input-stream-source-sink +.. includecode:: ../code/docs/stream/MigrationsJava.java#output-input-stream-source-sink \ No newline at end of file diff --git a/akka-docs-dev/rst/java/stream-composition.rst b/akka-docs/rst/java/stream/stream-composition.rst similarity index 86% rename from akka-docs-dev/rst/java/stream-composition.rst rename to akka-docs/rst/java/stream/stream-composition.rst index 27da645dd3..eca99bb41c 100644 --- a/akka-docs-dev/rst/java/stream-composition.rst +++ b/akka-docs/rst/java/stream/stream-composition.rst @@ -17,7 +17,7 @@ we illustrate the most common used stages viewed as "boxes". | -.. image:: ../images/compose_shapes.png +.. image:: ../../images/compose_shapes.png :align: center | @@ -42,7 +42,7 @@ hiding them behind a *shape* that looks like a :class:`Source`, :class:`Flow`, e | -.. image:: ../images/compose_composites.png +.. image:: ../../images/compose_composites.png :align: center | @@ -63,7 +63,7 @@ that is built from a composite :class:`Source` and a composite :class:`Sink` (wh | -.. image:: ../images/compose_nested_flow.png +.. image:: ../../images/compose_nested_flow.png :align: center | @@ -78,7 +78,7 @@ with the rest of the graph), but this demonstrates the uniform underlying model. If we try to build a code snippet that corresponds to the above diagram, our first try might look like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#non-nested-flow +.. includecode:: ../code/docs/stream/CompositionDocTest.java#non-nested-flow It is clear however that there is no nesting present in our first attempt, since the library cannot figure out where we intended to put composite module boundaries, it is our responsibility to do that. If we are using the @@ -87,7 +87,7 @@ methods ``withAttributes()`` or ``named()`` (where the latter is just a shorthan The following code demonstrates how to achieve the desired nesting: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#nested-flow +.. includecode:: ../code/docs/stream/CompositionDocTest.java#nested-flow Once we have hidden the internals of our components, they act like any other built-in component of similar shape. If we hide some of the internals of our composites, the result looks just like if any other predefine component has been @@ -95,7 +95,7 @@ used: | -.. image:: ../images/compose_nested_flow_opaque.png +.. image:: ../../images/compose_nested_flow_opaque.png :align: center | @@ -103,7 +103,7 @@ used: If we look at usage of built-in components, and our custom components, there is no difference in usage as the code snippet below demonstrates. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#reuse +.. includecode:: ../code/docs/stream/CompositionDocTest.java#reuse Composing complex systems ------------------------- @@ -119,7 +119,7 @@ As a first example, let's look at a more complex layout: | -.. image:: ../images/compose_graph.png +.. image:: ../../images/compose_graph.png :align: center | @@ -129,12 +129,12 @@ can be materialized) that encapsulates a non-trivial stream processing network. directed and non-directed cycles. The ``runnable()`` method of the :class:`GraphDSL` factory object allows the creation of a general, closed, and runnable graph. For example the network on the diagram can be realized like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#complex-graph +.. includecode:: ../code/docs/stream/CompositionDocTest.java#complex-graph In the code above we used the implicit port numbering feature to make the graph more readable and similar to the diagram. It is possible to refer to the ports, so another version might look like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#complex-graph-alt +.. includecode:: ../code/docs/stream/CompositionDocTest.java#complex-graph-alt | @@ -145,14 +145,14 @@ from the previous example, what remains is a partial graph: | -.. image:: ../images/compose_graph_partial.png +.. image:: ../../images/compose_graph_partial.png :align: center | We can recreate a similar graph in code, using the DSL in a similar way than before: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#partial-graph +.. includecode:: ../code/docs/stream/CompositionDocTest.java#partial-graph The only new addition is the return value of the builder block, which is a :class:`Shape`. All graphs (including :class:`Source`, :class:`BidiFlow`, etc) have a shape, which encodes the *typed* ports of the module. In our example @@ -165,14 +165,14 @@ it is a good practice to give names to modules to help debugging. | -.. image:: ../images/compose_graph_shape.png +.. image:: ../../images/compose_graph_shape.png :align: center | Since our partial graph has the right shape, it can be already used in the simpler, linear DSL: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#partial-use +.. includecode:: ../code/docs/stream/CompositionDocTest.java#partial-use It is not possible to use it as a :class:`Flow` yet, though (i.e. we cannot call ``.filter()`` on it), but :class:`Flow` has a ``wrap()`` method that just adds the DSL to a :class:`FlowShape`. There are similar methods on :class:`Source`, @@ -182,14 +182,14 @@ To demonstrate this, we will create the following graph: | -.. image:: ../images/compose_graph_flow.png +.. image:: ../../images/compose_graph_flow.png :align: center | The code version of the above closed graph might look like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#partial-flow-dsl +.. includecode:: ../code/docs/stream/CompositionDocTest.java#partial-flow-dsl .. note:: All graph builder sections check if the resulting graph has all ports connected except the exposed ones and will @@ -198,7 +198,7 @@ The code version of the above closed graph might look like this: We are still in debt of demonstrating that :class:`RunnableGraph` is a component just like any other, which can be embedded in graphs. In the following snippet we embed one closed graph in another: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#embed-closed +.. includecode:: ../code/docs/stream/CompositionDocTest.java#embed-closed The type of the imported module indicates that the imported module has a :class:`ClosedShape`, and so we are not able to wire it to anything else inside the enclosing closed graph. Nevertheless, this "island" is embedded properly, @@ -241,7 +241,7 @@ The propagation of the individual materialized values from the enclosed modules | -.. image:: ../images/compose_mat.png +.. image:: ../../images/compose_mat.png :align: center | @@ -250,29 +250,29 @@ To implement the above, first, we create a composite :class:`Source`, where the materialized type of :class:`Promise`. By using the combiner function ``Keep.left()``, the resulting materialized type is of the nested module (indicated by the color *red* on the diagram): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#mat-combine-1 +.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-1 Next, we create a composite :class:`Flow` from two smaller components. Here, the second enclosed :class:`Flow` has a materialized type of :class:`Future`, and we propagate this to the parent by using ``Keep.right()`` as the combiner function (indicated by the color *yellow* on the diagram): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#mat-combine-2 +.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-2 As a third step, we create a composite :class:`Sink`, using our ``nestedFlow`` as a building block. In this snippet, both the enclosed :class:`Flow` and the folding :class:`Sink` has a materialized value that is interesting for us, so we use ``Keep.both()`` to get a :class:`Pair` of them as the materialized type of ``nestedSink`` (indicated by the color *blue* on the diagram) -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#mat-combine-3 +.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-3 As the last example, we wire together ``nestedSource`` and ``nestedSink`` and we use a custom combiner function to create a yet another materialized type of the resulting :class:`RunnableGraph`. This combiner function just ignores the :class:`Future` part, and wraps the other two values in a custom case class :class:`MyClass` (indicated by color *purple* on the diagram): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#mat-combine-4a +.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-4a -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#mat-combine-4b +.. includecode:: ../code/docs/stream/CompositionDocTest.java#mat-combine-4b .. note:: The nested structure in the above example is not necessary for combining the materialized values, it just @@ -292,7 +292,7 @@ unless they override them with a custom value. The code below, a modification of an earlier example sets the ``inputBuffer`` attribute on certain modules, but not on others: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/CompositionDocTest.java#attributes-inheritance +.. includecode:: ../code/docs/stream/CompositionDocTest.java#attributes-inheritance The effect is, that each module inherits the ``inputBuffer`` attribute from its enclosing parent, unless it has the same attribute explicitly set. ``nestedSource`` gets the default attributes from the materializer itself. ``nestedSink`` @@ -301,7 +301,7 @@ except the ``map`` stage which has again an explicitly provided attribute overri | -.. image:: ../images/compose_attributes.png +.. image:: ../../images/compose_attributes.png :align: center | diff --git a/akka-docs-dev/rst/java/stream-cookbook.rst b/akka-docs/rst/java/stream/stream-cookbook.rst similarity index 83% rename from akka-docs-dev/rst/java/stream-cookbook.rst rename to akka-docs/rst/java/stream/stream-cookbook.rst index bb75ac44e1..fd15574834 100644 --- a/akka-docs-dev/rst/java/stream-cookbook.rst +++ b/akka-docs/rst/java/stream/stream-cookbook.rst @@ -32,12 +32,12 @@ Logging elements of a stream The simplest solution is to simply use a ``map`` operation and use ``println`` to print the elements received to the console. While this recipe is rather simplistic, it is often suitable for a quick debug session. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeLoggingElements.java#println-debug +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java#println-debug Another approach to logging is to use ``log()`` operation which allows configuring logging for elements flowing through the stream as well as completion and erroring. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeLoggingElements.java#log-custom +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeLoggingElements.java#log-custom Flattening a stream of sequences -------------------------------- @@ -49,7 +49,7 @@ The ``mapConcat`` operation can be used to implement a one-to-many transformatio in the form of ``In -> List``. In this case we want to map a ``List`` of elements to the elements in the collection itself, so we can just call ``mapConcat(l -> l)``. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeFlattenList.java#flattening-lists +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeFlattenList.java#flattening-lists Draining a stream to a strict collection ---------------------------------------- @@ -63,7 +63,7 @@ with maximum size of ``MaxAllowedSeqSize`` and then we take the first element of :class:`Future` containing a sequence with all the elements of the original up to ``MAX_ALLOWED_SIZE`` size (further elements are dropped). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeToStrict.java#draining-to-list +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeToStrict.java#draining-to-list Calculating the digest of a ByteString stream --------------------------------------------- @@ -83,9 +83,9 @@ we can emit further elements ``onPull`` is called again, and we see ``ctx.isFini source has been depleted already). Since we only want to emit a final element it is enough to call ``ctx.pushAndFinish`` passing the digest ByteString to be emitted. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeDigest.java#calculating-digest +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeDigest.java#calculating-digest -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeDigest.java#calculating-digest2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeDigest.java#calculating-digest2 .. _cookbook-parse-lines-java: @@ -98,7 +98,7 @@ needs to be parsed. The :class:`Framing` helper class contains a convenience method to parse messages from a stream of ``ByteStrings``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeParseLines.java#parse-lines +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeParseLines.java#parse-lines Implementing reduce-by-key -------------------------- @@ -128,7 +128,7 @@ If the ``groupBy`` operator encounters more keys than this number then the stream cannot continue without violating its resource bound, in this case ``groupBy`` will terminate with a failure. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeReduceByKeyTest.java#word-count +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java#word-count By extracting the parts specific to *wordcount* into @@ -138,9 +138,9 @@ By extracting the parts specific to *wordcount* into we get a generalized version below: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeReduceByKeyTest.java#reduce-by-key-general +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java#reduce-by-key-general -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeReduceByKeyTest.java#reduce-by-key-general2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeReduceByKeyTest.java#reduce-by-key-general2 .. note:: Please note that the reduce-by-key version we discussed above is sequential @@ -161,7 +161,7 @@ To achieve the desired result, we attack the problem in two steps: * Then we take this new stream of message topic pairs (containing a separate pair for each topic a given message belongs to) and feed it into groupBy, using the topic as the group key. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeMultiGroupByTest.java#multi-groupby +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeMultiGroupByTest.java#multi-groupby Working with Graphs =================== @@ -178,14 +178,14 @@ trigger signal arrives. This recipe solves the problem by simply zipping the stream of ``Message`` elments with the stream of ``Trigger`` signals. Since ``Zip`` produces pairs, we simply map the output stream selecting the first element of the pair. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeManualTrigger.java#manually-triggered-stream +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java#manually-triggered-stream Alternatively, instead of using a ``Zip``, and then using ``map`` to get the first element of the pairs, we can avoid creating the pairs in the first place by using ``ZipWith`` which takes a two argument function to produce the output element. If this function would return a pair of the two argument it would be exactly the behavior of ``Zip`` so ``ZipWith`` is a generalization of zipping. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeManualTrigger.java#manually-triggered-stream-zipwith +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeManualTrigger.java#manually-triggered-stream-zipwith Balancing jobs to a fixed pool of workers @@ -202,9 +202,9 @@ The graph consists of a ``Balance`` node which is a special fan-out operation th downstream consumers. In a ``for`` loop we wire all of our desired workers as outputs of this balancer element, then we wire the outputs of these workers to a ``Merge`` element that will collect the results from the workers. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeWorkerPool.java#worker-pool +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java#worker-pool -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeWorkerPool.java#worker-pool2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeWorkerPool.java#worker-pool2 Working with rate ================= @@ -228,7 +228,7 @@ case this is ``i -> i`` so our folding state starts form the message itself. The special: given the aggregate value (the last message) and the new element (the freshest element) our aggregate state becomes simply the freshest element. This choice of functions results in a simple dropping operation. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeSimpleDrop.java#simple-drop +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeSimpleDrop.java#simple-drop Dropping broadcast ------------------ @@ -243,9 +243,9 @@ defining a dropping strategy instead of the default ``Backpressure``. This allow between the different consumers (the buffer smooths out small rate variances), but also allows faster consumers to progress by dropping from the buffer of the slow consumers if necessary. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeDroppyBroadcast.java#droppy-bcast +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java#droppy-bcast -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeDroppyBroadcast.java#droppy-bcast2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeDroppyBroadcast.java#droppy-bcast2 Collecting missed ticks ----------------------- @@ -265,7 +265,7 @@ We will use ``conflate`` to solve the problem. Conflate takes two functions: As a result, we have a flow of ``Int`` where the number represents the missed ticks. A number 0 means that we were able to consume the tick fast enough (i.e. zero means: 1 non-missed tick + 0 missed ticks) -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeMissedTicks.java#missed-ticks +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeMissedTicks.java#missed-ticks Create a stream processor that repeats the last element seen ------------------------------------------------------------ @@ -283,7 +283,7 @@ to feed the downstream if no upstream element is ready yet. In the ``onPush()`` of ``onPull()``). The downstream ``onPull`` handler is very similar, we immediately relieve the downstream by emitting ``currentValue``. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeHold.java#hold-version-1 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeHold.java#hold-version-1 While it is relatively simple, the drawback of the first version is that it needs an arbitrary initial element which is not always possible to provide. Hence, we create a second version where the downstream might need to wait in one single @@ -296,7 +296,7 @@ version is that we call ``holdDownstream()`` if the first element is not yet ava upstream ``onPush()`` handler sets ``waitingFirstValue`` to false, and after checking if ``holdDownstream()`` has been called it either releaves the upstream producer, or both the upstream producer and downstream consumer by calling ``pushAndPull()`` -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeHold.java#hold-version-2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeHold.java#hold-version-2 Globally limiting the rate of a set of streams ---------------------------------------------- @@ -317,13 +317,13 @@ of the sender is added to a queue. Once the timer for replenishing the pending p message, we increment the pending permits counter and send a reply to each of the waiting senders. If there are more waiting senders than permits available we will stay in the ``closed`` state. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeGlobalRateLimit.java#global-limiter-actor +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java#global-limiter-actor To create a Flow that uses this global limiter actor we use the ``mapAsync`` function with the combination of the ``ask`` pattern. We also define a timeout, so if a reply is not received during the configured maximum wait period the returned future from ``ask`` will fail, which will fail the corresponding stream as well. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeGlobalRateLimit.java#global-limiter-flow +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeGlobalRateLimit.java#global-limiter-flow .. note:: The global actor used for limiting introduces a global bottleneck. You might want to assign a dedicated dispatcher @@ -349,9 +349,9 @@ which implements the following logic: Both ``onPush()`` and ``onPull()`` calls ``emitChunkOrPull()`` the only difference is that the push handler also stores the incoming chunk by appending to the end of the buffer. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeByteStrings.java#bytestring-chunker +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeByteStrings.java#bytestring-chunker -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeByteStrings.java#bytestring-chunker2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeByteStrings.java#bytestring-chunker2 Limit the number of bytes passing through a stream of ByteStrings ----------------------------------------------------------------- @@ -363,9 +363,9 @@ This recipe uses a :class:`PushStage` to implement the desired feature. In the o ``onPush()`` we just update a counter and see if it gets larger than ``maximumBytes``. If a violation happens we signal failure, otherwise we forward the chunk we have received. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeByteStrings.java#bytes-limiter +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeByteStrings.java#bytes-limiter -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeByteStrings.java#bytes-limiter2 +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeByteStrings.java#bytes-limiter2 Compact ByteStrings in a stream of ByteStrings ---------------------------------------------- @@ -377,7 +377,7 @@ chain we want to have clean copies that are no longer referencing the original B The recipe is a simple use of map, calling the ``compact()`` method of the :class:`ByteString` elements. This does copying of the underlying arrays, so this should be the last element of a long chain if used. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeByteStrings.java#compacting-bytestrings +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeByteStrings.java#compacting-bytestrings Injecting keep-alive messages into a stream of ByteStrings ---------------------------------------------------------- @@ -387,4 +387,4 @@ but only if this does not interfere with normal traffic. There is a built-in operation that allows to do this directly: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/cookbook/RecipeKeepAlive.java#inject-keepalive +.. includecode:: ../code/docs/stream/javadsl/cookbook/RecipeKeepAlive.java#inject-keepalive diff --git a/akka-docs-dev/rst/java/stream-customize.rst b/akka-docs/rst/java/stream/stream-customize.rst similarity index 91% rename from akka-docs-dev/rst/java/stream-customize.rst rename to akka-docs/rst/java/stream/stream-customize.rst index b5cb0a57c0..45d544a608 100644 --- a/akka-docs-dev/rst/java/stream-customize.rst +++ b/akka-docs/rst/java/stream/stream-customize.rst @@ -29,7 +29,7 @@ As a first motivating example, we will build a new :class:`Source` that will sim cancelled. To start, we need to define the "interface" of our stage, which is called *shape* in Akka Streams terminology (this is explained in more detail in the section :ref:`composition-java`). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#simple-source +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#simple-source As you see, in itself the :class:`GraphStage` only defines the ports of this stage and a shape that contains the ports. It also has a user implemented method called ``createLogic``. If you recall, stages are reusable in multiple @@ -50,7 +50,7 @@ that they are already usable in many situations, but do not provide the DSL meth ``Source.fromGraph`` (see :ref:`composition-java` for more details about graphs and DSLs). Now we can use the source as any other built-in one: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#simple-source-usage +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#simple-source-usage Port states, AbstractInHandler and AbstractOutHandler ----------------------------------------------------- @@ -84,7 +84,7 @@ in that state. | -.. image:: ../images/outport_transitions.png +.. image:: ../../images/outport_transitions.png :align: center | @@ -120,7 +120,7 @@ in that state. | -.. image:: ../images/inport_transitions.png +.. image:: ../../images/inport_transitions.png :align: center | @@ -165,7 +165,7 @@ flowing downstream. | -.. image:: ../images/graph_stage_conceptual.png +.. image:: ../../images/graph_stage_conceptual.png :align: center :width: 500 @@ -176,7 +176,7 @@ To illustrate these concepts we create a small :class:`GraphStage` that implemen | -.. image:: ../images/graph_stage_map.png +.. image:: ../../images/graph_stage_map.png :align: center :width: 300 @@ -185,7 +185,7 @@ To illustrate these concepts we create a small :class:`GraphStage` that implemen Map calls ``push(out)`` from the ``onPush()`` handler and it also calls ``pull()`` from the ``onPull`` handler resulting in the conceptual wiring above, and fully expressed in code below: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#one-to-one +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#one-to-one Map is a typical example of a one-to-one transformation of a stream where demand is passed along upstream elements passed on downstream. @@ -195,7 +195,7 @@ filter. The conceptual wiring of ``Filter`` looks like this: | -.. image:: ../images/graph_stage_filter.png +.. image:: ../../images/graph_stage_filter.png :align: center :width: 300 @@ -207,14 +207,14 @@ we return the “ball” to our upstream so that we get the new element. This is example by adding a conditional in the ``onPush`` handler and decide between a ``pull(in)`` or ``push(out)`` call (and of course not having a mapping ``f`` function). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#many-to-one +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#many-to-one To complete the picture we define a one-to-many transformation as the next step. We chose a straightforward example stage that emits every upstream element twice downstream. The conceptual wiring of this stage looks like this: | -.. image:: ../images/graph_stage_duplicate.png +.. image:: ../../images/graph_stage_duplicate.png :align: center :width: 300 @@ -224,7 +224,7 @@ This is a stage that has state: an option with the last element it has seen indi has duplicated this last element already or not. We must also make sure to emit the extra element if the upstream completes. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#one-to-many +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#one-to-many In this case a pull from downstream might be consumed by the stage itself rather than passed along upstream as the stage might contain an element it wants to @@ -237,7 +237,7 @@ This example can be simplified by replacing the usage of a mutable state with ca ``emitMultiple`` which will replace the handlers, emit each of multiple elements and then reinstate the original handlers: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#simpler-one-to-many +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#simpler-one-to-many Finally, to demonstrate all of the stages above, we put them together into a processing chain, which conceptually would correspond to the following structure: @@ -245,7 +245,7 @@ which conceptually would correspond to the following structure: | -.. image:: ../images/graph_stage_chain.png +.. image:: ../../images/graph_stage_chain.png :align: center :width: 700 @@ -253,7 +253,7 @@ which conceptually would correspond to the following structure: In code this is only a few lines, using the ``via`` use our custom stages in a stream: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#graph-stage-chain +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#graph-stage-chain If we attempt to draw the sequence of events, it shows that there is one "event token" in circulation in a potential chain of stages, just like our conceptual "railroad tracks" representation predicts. @@ -261,7 +261,7 @@ in circulation in a potential chain of stages, just like our conceptual "railroa | -.. image:: ../images/graph_stage_tracks_1.png +.. image:: ../../images/graph_stage_tracks_1.png :align: center :width: 700 @@ -299,7 +299,7 @@ In this sample the stage toggles between open and closed, where open means no el stage starts out as closed but as soon as an element is pushed downstream the gate becomes open for a duration of time during which it will consume and drop upstream messages: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#timed +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#timed Using asynchronous side-channels -------------------------------- @@ -318,7 +318,7 @@ Sharing the AsyncCallback from the constructor risks race conditions, therefore This example shows an asynchronous side channel graph stage that starts dropping elements when a future completes: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#async-side-channel +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#async-side-channel Integration with actors @@ -354,7 +354,7 @@ stage logic the materialized value must be provided In this sample the materialized value is a future containing the first element to go through the stream: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#materialized +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#materialized Using attributes to affect the behavior of a stage -------------------------------------------------- @@ -390,7 +390,7 @@ is seen from downstream. | -.. image:: ../images/graph_stage_detached_tracks_1.png +.. image:: ../../images/graph_stage_detached_tracks_1.png :align: center :width: 500 @@ -402,7 +402,7 @@ into the buffer stage. | -.. image:: ../images/graph_stage_detached_tracks_2.png +.. image:: ../../images/graph_stage_detached_tracks_2.png :align: center :width: 500 @@ -414,7 +414,7 @@ initialization. The buffer has demand for up to two elements without any downstr The following code example demonstrates a buffer class corresponding to the message sequence chart above. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphStageDocTest.java#detached +.. includecode:: ../code/docs/stream/GraphStageDocTest.java#detached Thread safety of custom processing stages ========================================= diff --git a/akka-docs-dev/rst/java/stream-error.rst b/akka-docs/rst/java/stream/stream-error.rst similarity index 73% rename from akka-docs-dev/rst/java/stream-error.rst rename to akka-docs/rst/java/stream/stream-error.rst index 5462ab4081..1a195ec22d 100644 --- a/akka-docs-dev/rst/java/stream-error.rst +++ b/akka-docs/rst/java/stream/stream-error.rst @@ -28,11 +28,11 @@ There are three ways to handle exceptions from application code: By default the stopping strategy is used for all exceptions, i.e. the stream will be completed with failure when an exception is thrown. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowErrorDocTest.java#stop +.. includecode:: ../code/docs/stream/FlowErrorDocTest.java#stop The default supervision strategy for a stream can be defined on the settings of the materializer. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowErrorDocTest.java#resume +.. includecode:: ../code/docs/stream/FlowErrorDocTest.java#resume Here you can see that all ``ArithmeticException`` will resume the processing, i.e. the elements that cause the division by zero are effectively dropped. @@ -44,12 +44,12 @@ elements that cause the division by zero are effectively dropped. The supervision strategy can also be defined for all operators of a flow. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowErrorDocTest.java#resume-section +.. includecode:: ../code/docs/stream/FlowErrorDocTest.java#resume-section ``Restart`` works in a similar way as ``Resume`` with the addition that accumulated state, if any, of the failing processing stage will be reset. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowErrorDocTest.java#restart-section +.. includecode:: ../code/docs/stream/FlowErrorDocTest.java#restart-section Errors from mapAsync ==================== @@ -61,11 +61,11 @@ discard those that cannot be found. We start with the tweet stream of authors: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#tweet-authors +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#tweet-authors Assume that we can lookup their email address using: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#email-address-lookup2 +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-address-lookup2 The ``Future`` is completed with ``Failure`` if the email is not found. @@ -73,7 +73,7 @@ Transforming the stream of authors to a stream of email addresses by using the ` service can be done with ``mapAsync`` and we use ``Supervision.getResumingDecider`` to drop unknown email addresses: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#email-addresses-mapAsync-supervision +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-addresses-mapAsync-supervision If we would not use ``Resume`` the default stopping strategy would complete the stream with failure on the first ``Future`` that was completed with ``Failure``. diff --git a/akka-docs-dev/rst/java/stream-flows-and-basics.rst b/akka-docs/rst/java/stream/stream-flows-and-basics.rst similarity index 94% rename from akka-docs-dev/rst/java/stream-flows-and-basics.rst rename to akka-docs/rst/java/stream/stream-flows-and-basics.rst index 941112663e..fdde891dcc 100644 --- a/akka-docs-dev/rst/java/stream-flows-and-basics.rst +++ b/akka-docs/rst/java/stream/stream-flows-and-basics.rst @@ -76,7 +76,7 @@ starting up Actors). Thanks to Flows being simply a description of the processin thread-safe, and freely shareable*, which means that it is for example safe to share and send them between actors, to have one actor prepare the work, and then have it be materialized at some completely different place in the code. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#materialization-in-steps +.. includecode:: ../code/docs/stream/FlowDocTest.java#materialization-in-steps After running (materializing) the ``RunnableGraph`` we get a special container object, the ``MaterializedMap``. Both sources and sinks are able to put specific objects into this map. Whether they put something in or not is implementation @@ -87,12 +87,12 @@ there is a convenience method called ``runWith()`` available for ``Sink``, ``Sou a supplied ``Source`` (in order to run a ``Sink``), a ``Sink`` (in order to run a ``Source``) or both a ``Source`` and a ``Sink`` (in order to run a ``Flow``, since it has neither attached yet). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#materialization-runWith +.. includecode:: ../code/docs/stream/FlowDocTest.java#materialization-runWith It is worth pointing out that since processing stages are *immutable*, connecting them returns a new processing stage, instead of modifying the existing instance, so while constructing long flows, remember to assign the new value to a variable or run it: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#source-immutable +.. includecode:: ../code/docs/stream/FlowDocTest.java#source-immutable .. note:: By default Akka Streams elements support **exactly one** downstream processing stage. @@ -108,7 +108,7 @@ In the example below we create two running materialized instance of the stream t variable, and both materializations give us a different ``Future`` from the map even though we used the same ``sink`` to refer to the future: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#stream-reuse +.. includecode:: ../code/docs/stream/FlowDocTest.java#stream-reuse Defining sources, sinks and flows --------------------------------- @@ -116,11 +116,11 @@ Defining sources, sinks and flows The objects :class:`Source` and :class:`Sink` define various ways to create sources and sinks of elements. The following examples show some of the most useful constructs (refer to the API documentation for more details): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#source-sink +.. includecode:: ../code/docs/stream/FlowDocTest.java#source-sink There are various ways to wire up different parts of a stream, the following examples show some of the available options: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#flow-connecting +.. includecode:: ../code/docs/stream/FlowDocTest.java#flow-connecting Illegal stream elements ----------------------- @@ -240,13 +240,13 @@ consequences: The first point can be countered by pre-fusing and then reusing a stream blueprint as sketched below: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#explicit-fusing +.. includecode:: ../code/docs/stream/FlowDocTest.java#explicit-fusing In order to balance the effects of the second and third bullet points you will have to insert asynchronous boundaries manually into your flows and graphs by way of adding ``Attributes.asyncBoundary`` to pieces that shall communicate with the rest of the graph in an asynchronous fashion. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#flow-async +.. includecode:: ../code/docs/stream/FlowDocTest.java#flow-async In this example we create two regions within the flow which will be executed in one Actor each—assuming that adding and multiplying integers is an extremely costly operation this will lead to a performance gain since two CPUs can @@ -256,7 +256,7 @@ by adding information to the flow graph that has been constructed up to this poi | -.. image:: ../images/asyncBoundary.png +.. image:: ../../images/asyncBoundary.png :align: center :width: 700 @@ -287,7 +287,7 @@ to somehow express how these values should be composed to a final value when we many combinator methods have variants that take an additional argument, a function, that will be used to combine the resulting values. Some examples of using these combiners are illustrated in the example below. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowDocTest.java#flow-mat-combine +.. includecode:: ../code/docs/stream/FlowDocTest.java#flow-mat-combine .. note:: diff --git a/akka-docs-dev/rst/java/stream-graphs.rst b/akka-docs/rst/java/stream/stream-graphs.rst similarity index 87% rename from akka-docs-dev/rst/java/stream-graphs.rst rename to akka-docs/rst/java/stream/stream-graphs.rst index d3b3dfe4db..97a3429021 100644 --- a/akka-docs-dev/rst/java/stream-graphs.rst +++ b/akka-docs/rst/java/stream/stream-graphs.rst @@ -45,13 +45,13 @@ One of the goals of the GraphDSL DSL is to look similar to how one would draw a simple to translate a design from whiteboard to code and be able to relate those two. Let's illustrate this by translating the below hand drawn graph into Akka Streams: -.. image:: ../images/simple-graph-example.png +.. image:: ../../images/simple-graph-example.png Such graph is simple to translate to the Graph DSL since each linear element corresponds to a :class:`Flow`, and each circle corresponds to either a :class:`Junction` or a :class:`Source` or :class:`Sink` if it is beginning or ending a :class:`Flow`. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowGraphDocTest.java#simple-flow-graph +.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#simple-flow-graph .. note:: Junction *reference equality* defines *graph node equality* (i.e. the same merge *instance* used in a GraphDSL @@ -75,7 +75,7 @@ In the example below we prepare a graph that consists of two parallel streams, in which we re-use the same instance of :class:`Flow`, yet it will properly be materialized as two connections between the corresponding Sources and Sinks: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowGraphDocTest.java#flow-graph-reusing-a-flow +.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#flow-graph-reusing-a-flow .. _partial-flow-graph-java: @@ -97,7 +97,7 @@ Let's imagine we want to provide users with a specialized element that given 3 i the greatest int value of each zipped triple. We'll want to expose 3 input ports (unconnected sources) and one output port (unconnected sink). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#simple-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocTest.java#simple-partial-flow-graph As you can see, first we construct the partial graph that describes how to compute the maximum of two input streams, then we reuse that twice while constructing the partial graph that extends this to three input streams, @@ -136,12 +136,12 @@ be attached before this Source can run”. Refer to the example below, in which we create a Source that zips together two numbers, to see this graph construction in action: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#source-from-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocTest.java#source-from-partial-flow-graph Similarly the same can be done for a ``Sink`` using ``SinkShape.of`` in which case the provided value must be an ``Inlet``. For defining a ``Flow`` we need to expose both an undefined source and sink: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#flow-from-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocTest.java#flow-from-partial-flow-graph Combining Sources and Sinks with simplified API ----------------------------------------------- @@ -150,11 +150,11 @@ There is simplified API you can use to combine sources and sinks with junctions ``Merge`` and ``Concat`` without the need for using the Graph DSL. The combine method takes care of constructing the necessary graph underneath. In following example we combine two sources into one (fan-in): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#source-combine +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocTest.java#source-combine The same can be done for a ``Sink`` but in this case it will be fan-out: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamPartialFlowGraphDocTest.java#sink-combine +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocTest.java#sink-combine .. _bidi-flow-java: @@ -171,14 +171,14 @@ this purpose exists the special type :class:`BidiFlow` which is a graph that has exactly two open inlets and two open outlets. The corresponding shape is called :class:`BidiShape` and is defined like this: -.. includecode:: ../../../akka-stream/src/main/scala/akka/stream/Shape.scala +.. includecode:: ../../../../akka-stream/src/main/scala/akka/stream/Shape.scala :include: bidi-shape :exclude: implementation-details-elided A bidirectional flow is defined just like a unidirectional :class:`Flow` as demonstrated for the codec mentioned above: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/BidiFlowDocTest.java +.. includecode:: ../code/docs/stream/BidiFlowDocTest.java :include: codec :exclude: implementation-details-elided @@ -187,7 +187,7 @@ case of a functional 1:1 transformation there is a concise convenience method as shown on the last line. The implementation of the two functions is not difficult either: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/BidiFlowDocTest.java#codec-impl +.. includecode:: ../code/docs/stream/BidiFlowDocTest.java#codec-impl In this way you could easily integrate any other serialization library that turns an object into a sequence of bytes. @@ -197,11 +197,11 @@ a framing protocol means that any received chunk of bytes may correspond to zero or more messages. This is best implemented using a :class:`GraphStage` (see also :ref:`graphstage-java`). -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/BidiFlowDocTest.java#framing +.. includecode:: ../code/docs/stream/BidiFlowDocTest.java#framing With these implementations we can build a protocol stack and test it: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/BidiFlowDocTest.java#compose +.. includecode:: ../code/docs/stream/BidiFlowDocTest.java#compose This example demonstrates how :class:`BidiFlow` subgraphs can be hooked together and also turned around with the ``.reversed()`` method. The test @@ -219,12 +219,12 @@ can be used in the graph as an ordinary source or outlet, and which will eventua If the materialized value is needed at more than one place, it is possible to call ``materializedValue`` any number of times to acquire the necessary number of outlets. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue +.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue Be careful not to introduce a cycle where the materialized value actually contributes to the materialized value. The following example demonstrates a case where the materialized ``Future`` of a fold is fed back to the fold itself. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue-cycle +.. includecode:: ../code/docs/stream/FlowGraphDocTest.java#flow-graph-matvalue-cycle .. _graph-cycles-java: @@ -240,7 +240,7 @@ The graph takes elements from the source, prints them, then broadcasts those ele to a consumer (we just used ``Sink.ignore`` for now) and to a feedback arc that is merged back into the main via a ``Merge`` junction. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphCyclesDocTest.java#deadlocked +.. includecode:: ../code/docs/stream/GraphCyclesDocTest.java#deadlocked Running this we observe that after a few numbers have been printed, no more elements are logged to the console - all processing stops after some time. After some investigation we observe that: @@ -258,7 +258,7 @@ If we modify our feedback loop by replacing the ``Merge`` junction with a ``Merg before trying the other lower priority input ports. Since we feed back through the preferred port it is always guaranteed that the elements in the cycles can flow. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphCyclesDocTest.java#unfair +.. includecode:: ../code/docs/stream/GraphCyclesDocTest.java#unfair If we run the example we see that the same sequence of numbers are printed over and over again, but the processing does not stop. Hence, we avoided the deadlock, but ``source`` is still @@ -273,7 +273,7 @@ of initial elements from ``source``. To make our cycle both live (not deadlocking) and fair we can introduce a dropping element on the feedback arc. In this case we chose the ``buffer()`` operation giving it a dropping strategy ``OverflowStrategy.dropHead``. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphCyclesDocTest.java#dropping +.. includecode:: ../code/docs/stream/GraphCyclesDocTest.java#dropping If we run this example we see that @@ -292,7 +292,7 @@ the beginning instead. To achieve this we modify our first graph by replacing th Since ``ZipWith`` takes one element from ``source`` *and* from the feedback arc to inject one element into the cycle, we maintain the balance of elements. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphCyclesDocTest.java#zipping-dead +.. includecode:: ../code/docs/stream/GraphCyclesDocTest.java#zipping-dead Still, when we try to run the example it turns out that no element is printed at all! After some investigation we realize that: @@ -304,7 +304,7 @@ These two conditions are a typical "chicken-and-egg" problem. The solution is to element into the cycle that is independent from ``source``. We do this by using a ``Concat`` junction on the backwards arc that injects a single element using ``Source.single``. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/GraphCyclesDocTest.java#zipping-live +.. includecode:: ../code/docs/stream/GraphCyclesDocTest.java#zipping-live When we run the above example we see that processing starts and never stops. The important takeaway from this example is that balanced cycles often need an initial "kick-off" element to be injected into the cycle. diff --git a/akka-docs-dev/rst/java/stream-integrations.rst b/akka-docs/rst/java/stream/stream-integrations.rst similarity index 81% rename from akka-docs-dev/rst/java/stream-integrations.rst rename to akka-docs/rst/java/stream/stream-integrations.rst index 3383f57eb1..1f7600d961 100644 --- a/akka-docs-dev/rst/java/stream-integrations.rst +++ b/akka-docs/rst/java/stream/stream-integrations.rst @@ -73,7 +73,7 @@ stream publisher that keeps track of the subscription life cycle and requested e Here is an example of such an actor. It dispatches incoming jobs to the attached subscriber: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ActorPublisherDocTest.java#job-manager +.. includecode:: ../code/docs/stream/ActorPublisherDocTest.java#job-manager You send elements to the stream by calling ``onNext``. You are allowed to send as many elements as have been requested by the stream subscriber. This amount can be inquired with @@ -105,7 +105,7 @@ More detailed information can be found in the API documentation. This is how it can be used as input :class:`Source` to a :class:`Flow`: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ActorPublisherDocTest.java#actor-publisher-usage +.. includecode:: ../code/docs/stream/ActorPublisherDocTest.java#actor-publisher-usage You can only attach one subscriber to this publisher. Use a ``Broadcast``-element or attach a ``Sink.asPublisher(true)`` to enable multiple subscribers. @@ -120,7 +120,7 @@ messages from the stream. It can also receive other, non-stream messages, in the Here is an example of such an actor. It dispatches incoming jobs to child worker actors: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ActorSubscriberDocTest.java#worker-pool +.. includecode:: ../code/docs/stream/ActorSubscriberDocTest.java#worker-pool Subclass must define the ``RequestStrategy`` to control stream back pressure. After each incoming message the ``AbstractActorSubscriber`` will automatically invoke @@ -138,7 +138,7 @@ More detailed information can be found in the API documentation. This is how it can be used as output :class:`Sink` to a :class:`Flow`: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ActorSubscriberDocTest.java#actor-subscriber-usage +.. includecode:: ../code/docs/stream/ActorSubscriberDocTest.java#actor-subscriber-usage Integrating with External Services ================================== @@ -149,24 +149,24 @@ performed with ``mapAsync`` or ``mapAsyncUnordered``. For example, sending emails to the authors of selected tweets using an external email service: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#email-server-send +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-server-send We start with the tweet stream of authors: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#tweet-authors +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#tweet-authors Assume that we can lookup their email address using: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#email-address-lookup +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-address-lookup Transforming the stream of authors to a stream of email addresses by using the ``lookupEmail`` service can be done with ``mapAsync``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#email-addresses-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#email-addresses-mapAsync Finally, sending the emails: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#send-emails +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#send-emails ``mapAsync`` is applying the given function that is calling out to the external service to each of the elements as they pass through this processing step. The function returns a :class:`Future` @@ -188,23 +188,23 @@ result stream onwards for further processing or storage. Note that ``mapAsync`` preserves the order of the stream elements. In this example the order is not important and then we can use the more efficient ``mapAsyncUnordered``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#external-service-mapAsyncUnordered +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#external-service-mapAsyncUnordered In the above example the services conveniently returned a :class:`Future` of the result. If that is not the case you need to wrap the call in a :class:`Future`. If the service call involves blocking you must also make sure that you run it on a dedicated execution context, to avoid starvation and disturbance of other tasks in the system. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#blocking-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#blocking-mapAsync The configuration of the ``"blocking-dispatcher"`` may look something like: -.. includecode:: ../scala/code/docs/stream/IntegrationDocSpec.scala#blocking-dispatcher-config +.. includecode:: ../../scala/code/docs/stream/IntegrationDocSpec.scala#blocking-dispatcher-config An alternative for blocking calls is to perform them in a ``map`` operation, still using a dedicated dispatcher for that operation. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#blocking-map +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#blocking-map However, that is not exactly the same as ``mapAsync``, since the ``mapAsync`` may run several calls concurrently, but ``map`` performs them one at a time. @@ -212,7 +212,7 @@ several calls concurrently, but ``map`` performs them one at a time. For a service that is exposed as an actor, or if an actor is used as a gateway in front of an external service, you can use ``ask``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#save-tweets +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#save-tweets Note that if the ``ask`` is not completed within the given timeout the stream is completed with failure. If that is not desired outcome you can use ``recover`` on the ``ask`` :class:`Future`. @@ -241,14 +241,14 @@ successive calls as long as there is downstream demand of several elements. Here is a fictive service that we can use to illustrate these aspects. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#sometimes-slow-service +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#sometimes-slow-service Elements starting with a lower case character are simulated to take longer time to process. Here is how we can use it with ``mapAsync``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#sometimes-slow-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#sometimes-slow-mapAsync The output may look like this: @@ -305,7 +305,7 @@ calls are limited by the buffer size (4) of the :class:`ActorMaterializerSetting Here is how we can use the same service with ``mapAsyncUnordered``: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/IntegrationDocTest.java#sometimes-slow-mapAsyncUnordered +.. includecode:: ../code/docs/stream/IntegrationDocTest.java#sometimes-slow-mapAsyncUnordered The output may look like this: @@ -383,19 +383,19 @@ An incomplete list of other implementations: The two most important interfaces in Reactive Streams are the :class:`Publisher` and :class:`Subscriber`. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#imports +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#imports Let us assume that a library provides a publisher of tweets: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#tweets-publisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#tweets-publisher and another library knows how to store author handles in a database: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#author-storage-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#author-storage-subscriber Using an Akka Streams :class:`Flow` we can transform the stream and connect those: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java :include: authors,connect-all The :class:`Publisher` is used as an input :class:`Source` to the flow and the @@ -405,24 +405,24 @@ A :class:`Flow` can also be also converted to a :class:`RunnableGraph[Processor[ materializes to a :class:`Processor` when ``run()`` is called. ``run()`` itself can be called multiple times, resulting in a new :class:`Processor` instance each time. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#flow-publisher-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#flow-publisher-subscriber A publisher can be connected to a subscriber with the ``subscribe`` method. It is also possible to expose a :class:`Source` as a :class:`Publisher` by using the Publisher-:class:`Sink`: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#source-publisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#source-publisher A publisher that is created with ``Sink.asPublisher(false)`` supports only a single subscription. Additional subscription attempts will be rejected with an :class:`IllegalStateException`. A publisher that supports multiple subscribers using fan-out/broadcasting is created as follows: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java :include: author-alert-subscriber,author-storage-subscriber -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#source-fanoutPublisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#source-fanoutPublisher The input buffer size of the stage controls how far apart the slowest subscriber can be from the fastest subscriber before slowing down the stream. @@ -430,11 +430,11 @@ before slowing down the stream. To make the picture complete, it is also possible to expose a :class:`Sink` as a :class:`Subscriber` by using the Subscriber-:class:`Source`: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#sink-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#sink-subscriber It is also possible to use re-wrap :class:`Processor` instances as a :class:`Flow` by passing a factory function that will create the :class:`Processor` instances: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/ReactiveStreamsDocTest.java#use-processor +.. includecode:: ../code/docs/stream/ReactiveStreamsDocTest.java#use-processor Please note that a factory is necessary to achieve reusability of the resulting :class:`Flow`. diff --git a/akka-docs-dev/rst/java/stream-introduction.rst b/akka-docs/rst/java/stream/stream-introduction.rst similarity index 100% rename from akka-docs-dev/rst/java/stream-introduction.rst rename to akka-docs/rst/java/stream/stream-introduction.rst diff --git a/akka-docs-dev/rst/java/stream-io.rst b/akka-docs/rst/java/stream/stream-io.rst similarity index 90% rename from akka-docs-dev/rst/java/stream-io.rst rename to akka-docs/rst/java/stream/stream-io.rst index 24715b03fa..b0563c66a2 100644 --- a/akka-docs-dev/rst/java/stream-io.rst +++ b/akka-docs/rst/java/stream/stream-io.rst @@ -19,7 +19,7 @@ Accepting connections: Echo Server In order to implement a simple EchoServer we ``bind`` to a given address, which returns a ``Source>``, which will emit an :class:`IncomingConnection` element for each new connection that the Server should handle: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamTcpDocTest.java#echo-server-simple-bind +.. includecode:: ../code/docs/stream/io/StreamTcpDocTest.java#echo-server-simple-bind Next, we simply handle *each* incoming connection using a :class:`Flow` which will be used as the processing stage to handle and emit ByteStrings from and to the TCP Socket. Since one :class:`ByteString` does not have to necessarily @@ -28,7 +28,7 @@ helper Flow from ``akka.stream.io.Framing`` to chunk the inputs up into actual l argument indicates that we require an explicit line ending even for the last message before the connection is closed. In this example we simply add exclamation marks to each incoming text message and push it through the flow: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamTcpDocTest.java#echo-server-simple-handle +.. includecode:: ../code/docs/stream/io/StreamTcpDocTest.java#echo-server-simple-handle Notice that while most building blocks in Akka Streams are reusable and freely shareable, this is *not* the case for the incoming connection Flow, since it directly corresponds to an existing, already accepted connection its handling can @@ -52,7 +52,7 @@ Let's say we know a server has exposed a simple command line interface over TCP, and would like to interact with it using Akka Streams over TCP. To open an outgoing connection socket we use the ``outgoingConnection`` method: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamTcpDocTest.java#repl-client +.. includecode:: ../code/docs/stream/io/StreamTcpDocTest.java#repl-client The ``repl`` flow we use to handle the server interaction first prints the servers response, then awaits on input from the command line (this blocking call is used here just for the sake of simplicity) and converts it to a @@ -84,7 +84,7 @@ Thankfully in most situations finding the right spot to start the conversation i to the protocol we are trying to implement using Streams. In chat-like applications, which our examples resemble, it makes sense to make the Server initiate the conversation by emitting a "hello" message: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamTcpDocTest.java#welcome-banner-chat-server +.. includecode:: ../code/docs/stream/io/StreamTcpDocTest.java#welcome-banner-chat-server The way we constructed a :class:`Flow` using the :class:`GraphDSL` is explained in detail in :ref:`constructing-sources-sinks-flows-from-partial-graphs-java`, however the basic concepts is rather simple– @@ -113,7 +113,7 @@ on files. Streaming data from a file is as easy as creating a `FileIO.fromFile` given a target file, and an optional ``chunkSize`` which determines the buffer size determined as one "element" in such stream: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamFileDocTest.java#file-source +.. includecode:: ../code/docs/stream/io/StreamFileDocTest.java#file-source Please note that these processing stages are backed by Actors and by default are configured to run on a pre-configured threadpool-backed dispatcher dedicated for File IO. This is very important as it isolates the blocking file IO operations from the rest @@ -121,4 +121,4 @@ of the ActorSystem allowing each dispatcher to be utilised in the most efficient dispatcher for file IO operations globally, you can do so by changing the ``akka.stream.blocking-io-dispatcher``, or for a specific stage by specifying a custom Dispatcher in code, like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/io/StreamFileDocTest.java#custom-dispatcher-code +.. includecode:: ../code/docs/stream/io/StreamFileDocTest.java#custom-dispatcher-code diff --git a/akka-docs-dev/rst/java/stream-parallelism.rst b/akka-docs/rst/java/stream/stream-parallelism.rst similarity index 92% rename from akka-docs-dev/rst/java/stream-parallelism.rst rename to akka-docs/rst/java/stream/stream-parallelism.rst index 812798895b..f8a4b07647 100644 --- a/akka-docs-dev/rst/java/stream-parallelism.rst +++ b/akka-docs/rst/java/stream/stream-parallelism.rst @@ -23,7 +23,7 @@ are two pancakes being cooked at the same time, one being cooked on its first si completion. This is how this setup would look like implemented as a stream: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowParallelismDocTest.java#pipelining +.. includecode:: ../code/docs/stream/FlowParallelismDocTest.java#pipelining The two ``map`` stages in sequence (encapsulated in the "frying pan" flows) will be executed in a pipelined way, basically doing the same as Roland with his frying pans: @@ -51,7 +51,7 @@ the results on a shared plate. Whenever a pan becomes empty, he takes the next s In essence he parallelizes the same process over multiple pans. This is how this setup will look like if implemented using streams: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowParallelismDocTest.java#parallelism +.. includecode:: ../code/docs/stream/FlowParallelismDocTest.java#parallelism The benefit of parallelizing is that it is easy to scale. In the pancake example it is easy to add a third frying pan with Patrik's method, but Roland cannot add a third frying pan, @@ -74,7 +74,7 @@ First, let's look at how we can parallelize pipelined processing stages. In the will employ two chefs, each working using Roland's pipelining method, but we use the two chefs in parallel, just like Patrik used the two frying pans. This is how it looks like if expressed as streams: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowParallelismDocTest.java#parallel-pipeline +.. includecode:: ../code/docs/stream/FlowParallelismDocTest.java#parallel-pipeline The above pattern works well if there are many independent jobs that do not depend on the results of each other, but the jobs themselves need multiple processing steps where each step builds on the result of @@ -91,7 +91,7 @@ It is also possible to organize parallelized stages into pipelines. This would m This is again straightforward to implement with the streams API: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/FlowParallelismDocTest.java#pipelined-parallel +.. includecode:: ../code/docs/stream/FlowParallelismDocTest.java#pipelined-parallel This usage pattern is less common but might be usable if a certain step in the pipeline might take wildly different times to finish different jobs. The reason is that there are more balance-merge steps in this pattern diff --git a/akka-docs-dev/rst/java/stream-quickstart.rst b/akka-docs/rst/java/stream/stream-quickstart.rst similarity index 85% rename from akka-docs-dev/rst/java/stream-quickstart.rst rename to akka-docs/rst/java/stream/stream-quickstart.rst index 2ec964d4bf..5853a5456a 100644 --- a/akka-docs-dev/rst/java/stream-quickstart.rst +++ b/akka-docs/rst/java/stream/stream-quickstart.rst @@ -15,7 +15,7 @@ allow to control what should happen in such scenarios. Here's the data model we'll be working with throughout the quickstart examples: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#model +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#model .. note:: @@ -31,7 +31,7 @@ like for example finding all twitter handles of users who tweet about ``#akka``. In order to prepare our environment by creating an :class:`ActorSystem` and :class:`ActorMaterializer`, which will be responsible for materializing and running the streams we are about to create: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#materializer-setup +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#materializer-setup The :class:`ActorMaterializer` can optionally take :class:`ActorMaterializerSettings` which can be used to define materialization properties, such as default buffer sizes (see also :ref:`stream-buffers-java`), the dispatcher to @@ -39,7 +39,7 @@ be used by the pipeline etc. These can be overridden with ``withAttributes`` on Let's assume we have a stream of tweets readily available. In Akka this is expressed as a :class:`Source`: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#tweet-source +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#tweet-source Streams always start flowing from a ``Source`` then can continue through ``Flow`` elements or more advanced graph elements to finally be consumed by a ``Sink``. @@ -53,7 +53,7 @@ The operations should look familiar to anyone who has used the Scala Collections however they operate on streams and not collections of data (which is a very important distinction, as some operations only make sense in streaming and vice versa): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#authors-filter-map +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#authors-filter-map Finally in order to :ref:`materialize ` and run the stream computation we need to attach the Flow to a ``Sink`` that will get the Flow running. The simplest way to do this is to call @@ -61,18 +61,18 @@ the Flow to a ``Sink`` that will get the Flow running. The simplest way to the `Sink class `_. For now let's simply print each author: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#authors-foreachsink-println +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#authors-foreachsink-println or by using the shorthand version (which are defined only for the most popular Sinks such as :class:`Sink.fold` and :class:`Sink.foreach`): -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#authors-foreach-println +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#authors-foreach-println Materializing and running a stream always requires a :class:`Materializer` to be passed in explicitly, like this: ``.run(mat)``. The complete snippet looks like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#first-sample +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#first-sample Flattening sequences in streams ------------------------------- @@ -81,7 +81,7 @@ we might want to map from one element to a number of elements and receive a "fla works on Scala Collections. In order to get a flattened stream of hashtags from our stream of tweets we can use the ``mapConcat`` combinator: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#hashtags-mapConcat +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#hashtags-mapConcat .. note:: The name ``flatMap`` was consciously avoided due to its proximity with for-comprehensions and monadic composition. @@ -109,7 +109,7 @@ at the expense of not reading as familiarly as collection transformations. Graphs are constructed using :class:`GraphDSL` like this: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#flow-graph-broadcast +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#flow-graph-broadcast As you can see, we use graph builder ``b`` to construct the graph using ``UniformFanOutShape`` and ``Flow`` s. @@ -140,7 +140,7 @@ in either ``OutOfMemoryError`` s or other severe degradations of service respons and must be handled explicitly. For example, if we are only interested in the "*most recent tweets, with a buffer of 10 elements*" this can be expressed using the ``buffer`` element: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-slow-consumption-dropHead +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-slow-consumption-dropHead The ``buffer`` element takes an explicit and required ``OverflowStrategy``, which defines how the buffer should react when it receives another element while it is full. Strategies provided include dropping the oldest element (``dropHead``), @@ -159,7 +159,7 @@ but in general it is possible to deal with finite streams and come up with a nic First, let's write such an element counter using ``Flow.of(Class)`` and ``Sink.fold`` to see how the types look like: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-fold-count +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-fold-count First we prepare a reusable ``Flow`` that will change each incoming tweet into an integer of value ``1``. We'll use this in order to combine those with a ``Sink.fold`` that will sum all ``Integer`` elements of the stream and make its result available as @@ -185,13 +185,13 @@ and materialized multiple times, because it is just the "blueprint" of the strea for example one that consumes a live stream of tweets within a minute, the materialized values for those two materializations will be different, as illustrated by this example: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-runnable-flow-materialized-twice +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-runnable-flow-materialized-twice Many elements in Akka Streams provide materialized values which can be used for obtaining either results of computation or steering these elements which will be discussed in detail in :ref:`stream-materialization-java`. Summing up this section, now we know what happens behind the scenes when we run this one-liner, which is equivalent to the multi line version above: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-fold-count-oneline +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocTest.java#tweets-fold-count-oneline .. note:: ``runWith()`` is a convenience method that automatically ignores the materialized value of any other stages except diff --git a/akka-docs-dev/rst/java/stream-rate.rst b/akka-docs/rst/java/stream/stream-rate.rst similarity index 80% rename from akka-docs-dev/rst/java/stream-rate.rst rename to akka-docs/rst/java/stream/stream-rate.rst index 1943bd6884..ae815a8743 100644 --- a/akka-docs-dev/rst/java/stream-rate.rst +++ b/akka-docs/rst/java/stream/stream-rate.rst @@ -8,7 +8,7 @@ Akka Streams processing stages are asynchronous and pipelined by default which m an element to its downstream consumer is able to immediately process the next message. To demonstrate what we mean by this, let's take a look at the following example: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#pipelining +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#pipelining Running the above example, one of the possible outputs looks like this: @@ -64,16 +64,16 @@ to a level suitable for the throughput requirements of the application. Default Alternatively they can be set by passing a :class:`ActorMaterializerSettings` to the materializer: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#materializer-buffer +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#materializer-buffer If the buffer size needs to be set for segments of a :class:`Flow` only, it is possible by defining a separate :class:`Flow` with these attributes: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#section-buffer +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#section-buffer Here is an example of a code that demonstrate some of the issues caused by internal buffers: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#buffering-abstraction-leak +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#buffering-abstraction-leak Running the above example one would expect the number *3* to be printed in every 3 seconds (the ``conflate`` step here is configured so that it counts the number of elements received before the downstream ``ZipWith`` consumes them). What @@ -97,7 +97,7 @@ pipeline of an application. The example below will ensure that 1000 jobs (but not more) are dequeued from an external (imaginary) system and stored locally in memory - relieving the external system: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-backpressure +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-backpressure The next example will also queue up 1000 jobs locally, but if there are more jobs waiting in the imaginary external systems, it makes space for the new element by @@ -105,12 +105,12 @@ dropping one element from the *tail* of the buffer. Dropping from the tail is a it must be noted that this will drop the *youngest* waiting job. If some "fairness" is desired in the sense that we want to be nice to jobs that has been waiting for long, then this option can be useful. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-droptail +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-droptail Instead of dropping the youngest element from the tail of the buffer a new element can be dropped without enqueueing it to the buffer at all. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-dropnew +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-dropnew Here is another example with a queue of 1000 jobs, but it makes space for the new element by dropping one element from the *head* of the buffer. This is the *oldest* @@ -119,13 +119,13 @@ resent if not processed in a certain period. The oldest element will be retransmitted soon, (in fact a retransmitted duplicate might be already in the queue!) so it makes sense to drop it first. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-drophead +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-drophead Compared to the dropping strategies above, dropBuffer drops all the 1000 jobs it has enqueued once the buffer gets full. This aggressive strategy is useful when dropping jobs is preferred to delaying jobs. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-dropbuffer +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-dropbuffer If our imaginary external job provider is a client using our API, we might want to enforce that the client cannot have more than 1000 queued jobs @@ -133,7 +133,7 @@ otherwise we consider it flooding and terminate the connection. This is easily achievable by the error strategy which simply fails the stream once the buffer gets full. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-fail +.. includecode:: ../code/docs/stream/StreamBuffersRateDocTest.java#explicit-buffers-fail Rate transformation =================== @@ -145,13 +145,13 @@ When a fast producer can not be informed to slow down by backpressure or some ot Below is an example snippet that summarizes fast stream of elements to a standart deviation, mean and count of elements that have arrived while the stats have been calculated. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/RateTransformationDocTest.java#conflate-summarize +.. includecode:: ../code/docs/stream/RateTransformationDocTest.java#conflate-summarize This example demonstrates that such flow's rate is decoupled. The element rate at the start of the flow can be much higher that the element rate at the end of the flow. Another possible use of ``conflate`` is to not consider all elements for summary when producer starts getting too fast. Example below demonstrates how ``conflate`` can be used to implement random drop of elements when consumer is not able to keep up with the producer. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/RateTransformationDocTest.java#conflate-sample +.. includecode:: ../code/docs/stream/RateTransformationDocTest.java#conflate-sample Understanding expand -------------------- @@ -160,10 +160,10 @@ Expand helps to deal with slow producers which are unable to keep up with the de As a simple use of ``expand`` here is a flow that sends the same element to consumer when producer does not send any new elements. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/RateTransformationDocTest.java#expand-last +.. includecode:: ../code/docs/stream/RateTransformationDocTest.java#expand-last Expand also allows to keep some state between demand requests from the downstream. Leveraging this, here is a flow that tracks and reports a drift between fast consumer and slow producer. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/RateTransformationDocTest.java#expand-drift +.. includecode:: ../code/docs/stream/RateTransformationDocTest.java#expand-drift Note that all of the elements coming from upstream will go through ``expand`` at least once. This means that the output of this flow is going to report a drift of zero if producer is fast enough, or a larger drift otherwise. diff --git a/akka-docs-dev/rst/java/stream-testkit.rst b/akka-docs/rst/java/stream/stream-testkit.rst similarity index 72% rename from akka-docs-dev/rst/java/stream-testkit.rst rename to akka-docs/rst/java/stream/stream-testkit.rst index aa8cfc97f7..68c62ea747 100644 --- a/akka-docs-dev/rst/java/stream-testkit.rst +++ b/akka-docs/rst/java/stream/stream-testkit.rst @@ -25,20 +25,20 @@ elements from a predefined collection, running a constructed test flow and asserting on the results that sink produced. Here is an example of a test for a sink: -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#strict-collection +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#strict-collection The same strategy can be applied for sources as well. In the next example we have a source that produces an infinite stream of elements. Such source can be tested by asserting that first arbitrary number of elements hold some condition. Here the ``grouped`` combinator and ``Sink.head`` are very useful. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#grouped-infinite +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#grouped-infinite When testing a flow we need to attach a source and a sink. As both stream ends are under our control, we can choose sources that tests various edge cases of the flow and sinks that ease assertions. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#folded-stream +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#folded-stream TestKit ======= @@ -51,7 +51,7 @@ One of the more straightforward tests would be to materialize stream to a :class:`Future` and then use ``pipe`` pattern to pipe the result of that future to the probe. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#pipeto-testprobe +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#pipeto-testprobe Instead of materializing to a future, we can use a :class:`Sink.actorRef` that sends all incoming elements to the given :class:`ActorRef`. Now we can use @@ -59,13 +59,13 @@ assertion methods on :class:`TestProbe` and expect elements one by one as they arrive. We can also assert stream completion by expecting for ``onCompleteMessage`` which was given to :class:`Sink.actorRef`. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#sink-actorref +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#sink-actorref Similarly to :class:`Sink.actorRef` that provides control over received elements, we can use :class:`Source.actorRef` and have full control over elements to be sent. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#source-actorref +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#source-actorref Streams TestKit =============== @@ -83,18 +83,18 @@ provide sources and sinks that materialize to probes that allow fluent API. A sink returned by ``TestSink.probe`` allows manual control over demand and assertions over elements coming downstream. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#test-sink-probe +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#test-sink-probe A source returned by ``TestSource.probe`` can be used for asserting demand or controlling when stream is completed or ended with an error. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#test-source-probe +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#test-source-probe You can also inject exceptions and test sink behaviour on error conditions. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#injecting-failure +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#injecting-failure Test source and sink can be used together in combination when testing flows. -.. includecode:: ../../../akka-samples/akka-docs-java-lambda/src/test/java/docs/stream/StreamTestKitDocTest.java#test-source-and-sink +.. includecode:: ../code/docs/stream/StreamTestKitDocTest.java#test-source-and-sink diff --git a/akka-docs/rst/project/migration-guide-2.3.x-2.4.x.rst b/akka-docs/rst/project/migration-guide-2.3.x-2.4.x.rst index 4dcde879c3..031a7915df 100644 --- a/akka-docs/rst/project/migration-guide-2.3.x-2.4.x.rst +++ b/akka-docs/rst/project/migration-guide-2.3.x-2.4.x.rst @@ -673,9 +673,12 @@ Be careful to not do any operations on the ``Future[Terminated]`` using the ``sy as ``ExecutionContext`` as it will be shut down with the ``ActorSystem``, instead use for example the Scala standard library context from ``scala.concurrent.ExecutionContext.global``. +:: + // import system.dispatcher <- this would not work import scala.concurrent.ExecutionContext.Implicits.global system.terminate().foreach { _ => println("Actor system was shut down") } + diff --git a/akka-docs/rst/scala.rst b/akka-docs/rst/scala.rst index 473b199f76..bce3187bef 100644 --- a/akka-docs/rst/scala.rst +++ b/akka-docs/rst/scala.rst @@ -12,6 +12,8 @@ Scala Documentation scala/index-futures scala/index-network scala/index-utilities + scala/stream/index + scala/http/index scala/howto experimental/index dev/index diff --git a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala index 95406a9bbd..70efa56009 100644 --- a/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala +++ b/akka-docs/rst/scala/code/docs/actor/ActorDocSpec.scala @@ -21,15 +21,21 @@ import akka.util._ import scala.concurrent.duration._ import scala.concurrent.Await -//#my-actor -class MyActor extends Actor { - val log = Logging(context.system, this) - def receive = { - case "test" => log.info("received test") - case _ => log.info("received unknown message") +object x { + + //#my-actor + class MyActor extends Actor { + val log = Logging(context.system, this) + + def receive = { + case "test" => log.info("received test") + case _ => log.info("received unknown message") + } } + + //#my-actor } -//#my-actor +import x._ final case class DoIt(msg: ImmutableMessage) final case class Message(s: String) @@ -54,6 +60,7 @@ class DemoActorWrapper extends Actor { object DemoActor { /** * Create Props for an actor of this type. + * * @param magicNumber The magic number to be passed to this actor’s constructor. * @return a Props for creating this actor, which can then be further configured * (e.g. calling `.withDispatcher()` on it) @@ -257,7 +264,10 @@ final case class Give(thing: Any) //#receive-orElse -class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) { +class ActorDocSpec extends AkkaSpec(""" + akka.loglevel = INFO + akka.loggers = [] + """) { "import context" in { new AnyRef { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpClientExampleSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/HttpClientExampleSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpClientExampleSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/HttpClientExampleSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/HttpServerExampleSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/MarshalSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/MarshalSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/MarshalSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/MarshalSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/ModelSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/ModelSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/ModelSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/ModelSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/SprayJsonExampleSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/SprayJsonExampleSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/SprayJsonExampleSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/SprayJsonExampleSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/UnmarshalSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/UnmarshalSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/UnmarshalSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/UnmarshalSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala similarity index 99% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala index bede052ddb..fa209f125e 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala @@ -4,6 +4,8 @@ package docs.http.scaladsl.server + + /* import org.scalatest.Inside import akka.http.scaladsl.server._ diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/DirectiveExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/DirectiveExamplesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/DirectiveExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/DirectiveExamplesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/FileUploadExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/FileUploadExamplesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/FileUploadExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/FileUploadExamplesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/FullTestKitExampleSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/FullTestKitExampleSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/FullTestKitExampleSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/FullTestKitExampleSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/RoutingSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/RoutingSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/RoutingSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/RoutingSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/WebsocketExampleSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/WebsocketExampleSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/WebsocketExampleSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/WebsocketExampleSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala similarity index 99% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala index 7030faaec0..b56c8042bd 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala @@ -2,8 +2,7 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import java.io.File @@ -16,6 +15,7 @@ import akka.http.scaladsl.server._ import akka.stream.ActorMaterializer import akka.stream.scaladsl.{ FileIO, Sink, Source } import akka.util.ByteString +import docs.http.scaladsl.server.RoutingSpec import scala.concurrent.Future import scala.util.control.NonFatal diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala similarity index 98% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala index 7276cac7f9..90ff9e4208 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala @@ -2,10 +2,10 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.coding._ +import docs.http.scaladsl.server.RoutingSpec import akka.http.scaladsl.model.{ HttpResponse, StatusCodes } import akka.http.scaladsl.model.headers.{ HttpEncodings, HttpEncoding, `Accept-Encoding`, `Content-Encoding` } import akka.http.scaladsl.model.headers.HttpEncodings._ diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala similarity index 95% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala index 090a19dd4f..f146daf062 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CookieDirectivesExamplesSpec.scala @@ -2,11 +2,11 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.server._ import akka.http.scaladsl.model.headers.{ HttpCookie, Cookie, `Set-Cookie` } +import docs.http.scaladsl.server.RoutingSpec import akka.http.scaladsl.model.DateTime class CookieDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala index c77709484c..626a1997bf 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/CustomDirectivesExamplesSpec.scala @@ -1,8 +1,7 @@ /** * Copyright (C) 2009-2015 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.server.{ Directive1, Directive } import docs.http.scaladsl.server.RoutingSpec diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala similarity index 97% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala index 7d0ba017ca..ae68777fbb 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala @@ -2,12 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.event.Logging import akka.http.scaladsl.model.{ HttpRequest, HttpResponse } import akka.http.scaladsl.server.directives.{ DebuggingDirectives, LogEntry, LoggingMagnet } +import docs.http.scaladsl.server.RoutingSpec class DebuggingDirectivesExamplesSpec extends RoutingSpec { "logRequest-0" in { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala similarity index 95% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala index daafbdd7e6..167f1a653c 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ExecutionDirectivesExamplesSpec.scala @@ -2,11 +2,11 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server._ +import docs.http.scaladsl.server.RoutingSpec class ExecutionDirectivesExamplesSpec extends RoutingSpec { "handleExceptions" in { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala similarity index 98% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala index 441e1a841d..1fb1013a57 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FileAndResourceDirectivesExamplesSpec.scala @@ -9,6 +9,7 @@ import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.directives.DirectoryListing import akka.http.scaladsl.server.directives.FileAndResourceDirectives.DirectoryRenderer import docs.http.scaladsl.server.RoutingSpec +import docs.http.scaladsl.server.RoutingSpec class FileAndResourceDirectivesExamplesSpec extends RoutingSpec { "getFromFile-examples" in compileOnlySpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala similarity index 93% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala index 4824c46880..cb4ed72944 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FormFieldDirectivesExamplesSpec.scala @@ -2,11 +2,11 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.server.Route import akka.http.scaladsl.model._ +import docs.http.scaladsl.server.RoutingSpec class FormFieldDirectivesExamplesSpec extends RoutingSpec { "formFields" in { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala index 6beb509d1b..cec10456ba 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala @@ -2,10 +2,11 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import java.util.concurrent.TimeUnit +import docs.http.scaladsl.server.RoutingSpec + import scala.concurrent.Future import scala.util.{ Success, Failure } import akka.http.scaladsl.server.ExceptionHandler diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala similarity index 98% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala index 38c0fdcb76..f4ef75dc64 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HeaderDirectivesExamplesSpec.scala @@ -2,12 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server.MissingHeaderRejection import akka.http.scaladsl.server.Route +import docs.http.scaladsl.server.RoutingSpec import headers._ import StatusCodes._ import org.scalatest.Inside diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala similarity index 95% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala index f3e3d5ecea..9167d57908 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/HostDirectivesExamplesSpec.scala @@ -2,10 +2,10 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ +import docs.http.scaladsl.server.RoutingSpec import headers._ import StatusCodes._ diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala index 1581c09655..4d017e90c1 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala @@ -2,10 +2,10 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport +import docs.http.scaladsl.server.RoutingSpec import akka.http.scaladsl.model.MediaTypes.`application/json` import akka.http.scaladsl.model._ import spray.json.DefaultJsonProtocol diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala similarity index 97% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala index b9b1efb515..605637397e 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MethodDirectivesExamplesSpec.scala @@ -2,11 +2,11 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Route +import docs.http.scaladsl.server.RoutingSpec class MethodDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala index eacabc5f86..9172d4ca9e 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala @@ -2,12 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server._ import headers._ +import docs.http.scaladsl.server.RoutingSpec class MiscDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala similarity index 98% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala index 6824e3c03e..b14abcd0a8 100755 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/ParameterDirectivesExamplesSpec.scala @@ -2,12 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Route import akka.http.scaladsl.unmarshalling.PredefinedFromStringUnmarshallers +import docs.http.scaladsl.server.RoutingSpec class ParameterDirectivesExamplesSpec extends RoutingSpec with PredefinedFromStringUnmarshallers { "example-1" in { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala similarity index 99% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala index ad71b04d59..500f39016b 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala @@ -2,11 +2,11 @@ * Copyright (C) 2009-2015 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.server._ +import docs.http.scaladsl.server.RoutingSpec class PathDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala similarity index 95% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala index c2933e208c..9b39fe945e 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RangeDirectivesExamplesSpec.scala @@ -2,8 +2,7 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import com.typesafe.config.{ ConfigFactory, Config } @@ -12,6 +11,7 @@ import akka.util.ByteString import headers._ import scala.concurrent.Await import scala.concurrent.duration._ +import docs.http.scaladsl.server.RoutingSpec class RangeDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala index ff0b71619d..98d9053a08 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RespondWithDirectivesExamplesSpec.scala @@ -2,10 +2,10 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model.headers._ +import docs.http.scaladsl.server.RoutingSpec class RespondWithDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala index 74bbaac0ca..7cfd72e690 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala @@ -2,12 +2,12 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server.{ Route, ValidationRejection } import akka.testkit.EventFilter +import docs.http.scaladsl.server.RoutingSpec class RouteDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala similarity index 92% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala index d31a79b29a..866940985c 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SchemeDirectivesExamplesSpec.scala @@ -2,8 +2,8 @@ * Copyright (C) 2009-2014 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives +import docs.http.scaladsl.server.RoutingSpec class SchemeDirectivesExamplesSpec extends RoutingSpec { "example-1" in { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala similarity index 99% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala index d0de7d3954..37d0297730 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/SecurityDirectivesExamplesSpec.scala @@ -2,8 +2,7 @@ * Copyright (C) 2009-2015 Typesafe Inc. */ -package docs.http.scaladsl.server -package directives +package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers._ @@ -11,6 +10,7 @@ import akka.http.scaladsl.server.Route import akka.http.scaladsl.server.directives.Credentials import scala.concurrent.Future +import docs.http.scaladsl.server.RoutingSpec class SecurityDirectivesExamplesSpec extends RoutingSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala similarity index 99% rename from akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala rename to akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala index ab807fba90..881baeeed0 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala +++ b/akka-docs/rst/scala/code/docs/http/scaladsl/server/directives/WebsocketDirectivesExamplesSpec.scala @@ -12,7 +12,6 @@ import akka.stream.OverflowStrategy import akka.stream.scaladsl.{ Sink, Source, Flow } import docs.http.scaladsl.server.RoutingSpec - import akka.http.scaladsl.model.ws.{ TextMessage, Message, BinaryMessage } import akka.http.scaladsl.testkit.WSProbe diff --git a/akka-docs-dev/rst/scala/code/docs/stream/ActorPublisherDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/ActorPublisherDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/ActorPublisherDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/ActorPublisherDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/ActorSubscriberDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/ActorSubscriberDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/ActorSubscriberDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/ActorSubscriberDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/BidiFlowDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/BidiFlowDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/BidiFlowDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/BidiFlowDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/CompositionDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/CompositionDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/CompositionDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/CompositionDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/FlowDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/FlowDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/FlowDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowErrorDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/FlowErrorDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/FlowErrorDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/FlowErrorDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowGraphDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/FlowGraphDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/FlowGraphDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/FlowGraphDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowParallelismDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/FlowParallelismDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/FlowParallelismDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/FlowParallelismDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala b/akka-docs/rst/scala/code/docs/stream/FlowStagesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/FlowStagesSpec.scala rename to akka-docs/rst/scala/code/docs/stream/FlowStagesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/GraphCyclesSpec.scala b/akka-docs/rst/scala/code/docs/stream/GraphCyclesSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/GraphCyclesSpec.scala rename to akka-docs/rst/scala/code/docs/stream/GraphCyclesSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/GraphStageDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/GraphStageDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/GraphStageDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/GraphStageDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/IntegrationDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/IntegrationDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/IntegrationDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/IntegrationDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/MigrationsScala.scala b/akka-docs/rst/scala/code/docs/stream/MigrationsScala.scala similarity index 94% rename from akka-docs-dev/rst/scala/code/docs/MigrationsScala.scala rename to akka-docs/rst/scala/code/docs/stream/MigrationsScala.scala index 37357c098b..3f25f78bd1 100644 --- a/akka-docs-dev/rst/scala/code/docs/MigrationsScala.scala +++ b/akka-docs/rst/scala/code/docs/stream/MigrationsScala.scala @@ -1,16 +1,19 @@ -package docs +/** + * Copyright (C) 2015 Typesafe Inc. + */ +package docs.stream -import java.io.{ InputStream, File } +import java.io.File -import akka.http.scaladsl.model.Uri -import akka.stream.scaladsl._ -import akka.stream._ -import akka.stream.stage.{ OutHandler, InHandler, GraphStageLogic, GraphStage } -import akka.stream.testkit.{ AkkaSpec, TestPublisher, TestSubscriber } +import _root_.akka.http.scaladsl.model.Uri +import _root_.akka.stream._ +import _root_.akka.stream.scaladsl._ +import _root_.akka.stream.stage.{GraphStage, GraphStageLogic, InHandler, OutHandler} +import _root_.akka.stream.testkit.{AkkaSpec, TestPublisher, TestSubscriber} -import scala.concurrent.{ Future, ExecutionContext, Promise } import scala.concurrent.duration._ -import scala.util.{ Failure, Random, Success, Try } +import scala.concurrent.{ExecutionContext, Future, Promise} +import scala.util.{Failure, Random, Success, Try} class MigrationsScala extends AkkaSpec { diff --git a/akka-docs-dev/rst/scala/code/docs/stream/RateTransformationDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/RateTransformationDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/RateTransformationDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/RateTransformationDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/ReactiveStreamsDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/ReactiveStreamsDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/ReactiveStreamsDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/ReactiveStreamsDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala b/akka-docs/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala rename to akka-docs/rst/scala/code/docs/stream/StreamBuffersRateSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamPartialFlowGraphDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/StreamPartialFlowGraphDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/StreamPartialFlowGraphDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/StreamPartialFlowGraphDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/StreamTestKitDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/StreamTestKitDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/StreamTestKitDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/StreamTestKitDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/TwitterStreamQuickstartDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/TwitterStreamQuickstartDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/TwitterStreamQuickstartDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/TwitterStreamQuickstartDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeByteStrings.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeByteStrings.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeByteStrings.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeByteStrings.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala similarity index 96% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala index 3203890b08..dcad4e53fe 100644 --- a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala +++ b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeCollectingMetrics.scala @@ -75,7 +75,7 @@ class RecipeCollectingMetrics extends RecipeSpec { // To finish the recipe, we simply use :class:`ZipWith` to trigger reading the latest value from the ``currentLoad`` // stream whenever a new ``Tick`` arrives on the stream of ticks, ``reportTicks``. // - // .. includecode:: code/docs/stream/cookbook/RecipeCollectingMetrics.scala#periodic-metrics-collection + // .. includecode:: ../code/docs/stream/cookbook/RecipeCollectingMetrics.scala#periodic-metrics-collection // // .. warning:: // In order for this recipe to work the buffer size for the :class:`ZipWith` must be set to 1. The reason for this is diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeDigest.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeDigest.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeDigest.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeDigest.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeDroppyBroadcast.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeDroppyBroadcast.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeDroppyBroadcast.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeDroppyBroadcast.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeFlattenSeq.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeFlattenSeq.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeFlattenSeq.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeFlattenSeq.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeGlobalRateLimit.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeGlobalRateLimit.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeGlobalRateLimit.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeGlobalRateLimit.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeHold.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeHold.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeHold.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeHold.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeKeepAlive.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeLoggingElements.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeLoggingElements.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeLoggingElements.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeLoggingElements.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeManualTrigger.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeManualTrigger.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeManualTrigger.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeManualTrigger.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeMissedTicks.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeMissedTicks.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeMissedTicks.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeMissedTicks.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeMultiGroupBy.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeMultiGroupBy.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeMultiGroupBy.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeMultiGroupBy.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeParseLines.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeParseLines.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeParseLines.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeParseLines.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeReduceByKey.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeReduceByKey.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeReduceByKey.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeReduceByKey.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeSimpleDrop.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeSimpleDrop.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeSimpleDrop.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeSimpleDrop.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeSpec.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeSpec.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeToStrict.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeToStrict.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeToStrict.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeToStrict.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeWorkerPool.scala b/akka-docs/rst/scala/code/docs/stream/cookbook/RecipeWorkerPool.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/cookbook/RecipeWorkerPool.scala rename to akka-docs/rst/scala/code/docs/stream/cookbook/RecipeWorkerPool.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/io/StreamFileDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/io/StreamFileDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/io/StreamFileDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/io/StreamFileDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala b/akka-docs/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala rename to akka-docs/rst/scala/code/docs/stream/io/StreamTcpDocSpec.scala diff --git a/akka-docs-dev/rst/scala/code/docs/utils/TestUtils.scala b/akka-docs/rst/scala/code/docs/utils/TestUtils.scala similarity index 100% rename from akka-docs-dev/rst/scala/code/docs/utils/TestUtils.scala rename to akka-docs/rst/scala/code/docs/utils/TestUtils.scala diff --git a/akka-docs-dev/rst/scala/http/client-side/connection-level.rst b/akka-docs/rst/scala/http/client-side/connection-level.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/connection-level.rst rename to akka-docs/rst/scala/http/client-side/connection-level.rst diff --git a/akka-docs-dev/rst/scala/http/client-side/host-level.rst b/akka-docs/rst/scala/http/client-side/host-level.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/host-level.rst rename to akka-docs/rst/scala/http/client-side/host-level.rst diff --git a/akka-docs-dev/rst/scala/http/client-side/https-support.rst b/akka-docs/rst/scala/http/client-side/https-support.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/https-support.rst rename to akka-docs/rst/scala/http/client-side/https-support.rst diff --git a/akka-docs-dev/rst/scala/http/client-side/index.rst b/akka-docs/rst/scala/http/client-side/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/index.rst rename to akka-docs/rst/scala/http/client-side/index.rst diff --git a/akka-docs-dev/rst/scala/http/client-side/request-level.rst b/akka-docs/rst/scala/http/client-side/request-level.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/request-level.rst rename to akka-docs/rst/scala/http/client-side/request-level.rst diff --git a/akka-docs-dev/rst/scala/http/client-side/websocket-support.rst b/akka-docs/rst/scala/http/client-side/websocket-support.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/client-side/websocket-support.rst rename to akka-docs/rst/scala/http/client-side/websocket-support.rst diff --git a/akka-docs-dev/rst/scala/http/common/de-coding.rst b/akka-docs/rst/scala/http/common/de-coding.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/de-coding.rst rename to akka-docs/rst/scala/http/common/de-coding.rst diff --git a/akka-docs-dev/rst/scala/http/common/http-model.rst b/akka-docs/rst/scala/http/common/http-model.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/http-model.rst rename to akka-docs/rst/scala/http/common/http-model.rst diff --git a/akka-docs-dev/rst/scala/http/common/index.rst b/akka-docs/rst/scala/http/common/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/index.rst rename to akka-docs/rst/scala/http/common/index.rst diff --git a/akka-docs-dev/rst/scala/http/common/json-support.rst b/akka-docs/rst/scala/http/common/json-support.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/json-support.rst rename to akka-docs/rst/scala/http/common/json-support.rst diff --git a/akka-docs-dev/rst/scala/http/common/marshalling.rst b/akka-docs/rst/scala/http/common/marshalling.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/marshalling.rst rename to akka-docs/rst/scala/http/common/marshalling.rst diff --git a/akka-docs-dev/rst/scala/http/common/unmarshalling.rst b/akka-docs/rst/scala/http/common/unmarshalling.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/unmarshalling.rst rename to akka-docs/rst/scala/http/common/unmarshalling.rst diff --git a/akka-docs-dev/rst/scala/http/common/xml-support.rst b/akka-docs/rst/scala/http/common/xml-support.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/common/xml-support.rst rename to akka-docs/rst/scala/http/common/xml-support.rst diff --git a/akka-docs-dev/rst/scala/http/configuration.rst b/akka-docs/rst/scala/http/configuration.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/configuration.rst rename to akka-docs/rst/scala/http/configuration.rst diff --git a/akka-docs-dev/rst/scala/http/index.rst b/akka-docs/rst/scala/http/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/index.rst rename to akka-docs/rst/scala/http/index.rst diff --git a/akka-docs-dev/rst/scala/http/introduction.rst b/akka-docs/rst/scala/http/introduction.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/introduction.rst rename to akka-docs/rst/scala/http/introduction.rst diff --git a/akka-docs-dev/rst/scala/http/low-level-server-side-api.rst b/akka-docs/rst/scala/http/low-level-server-side-api.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/low-level-server-side-api.rst rename to akka-docs/rst/scala/http/low-level-server-side-api.rst diff --git a/akka-docs-dev/rst/scala/http/migration-from-spray.rst b/akka-docs/rst/scala/http/migration-from-spray.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/migration-from-spray.rst rename to akka-docs/rst/scala/http/migration-from-spray.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/case-class-extraction.rst b/akka-docs/rst/scala/http/routing-dsl/case-class-extraction.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/case-class-extraction.rst rename to akka-docs/rst/scala/http/routing-dsl/case-class-extraction.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/alphabetically.rst b/akka-docs/rst/scala/http/routing-dsl/directives/alphabetically.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/alphabetically.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/alphabetically.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejection.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejection.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejection.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejection.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejections.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejections.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejections.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/cancelRejections.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extract.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extract.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extract.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extract.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractExecutionContext.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractExecutionContext.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractExecutionContext.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractExecutionContext.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractLog.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractLog.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractLog.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractLog.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractMaterializer.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractMaterializer.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractMaterializer.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractMaterializer.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractRequest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractRequest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractRequest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractRequest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractRequestContext.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractRequestContext.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractRequestContext.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractRequestContext.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractSettings.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractSettings.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractSettings.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractSettings.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractUnmatchedPath.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractUnmatchedPath.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractUnmatchedPath.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractUnmatchedPath.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractUri.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractUri.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/extractUri.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/extractUri.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapInnerRoute.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapInnerRoute.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapInnerRoute.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapInnerRoute.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRejections.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRejections.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRejections.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRejections.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRequest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRequest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRequest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRequest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRequestContext.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRequestContext.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRequestContext.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRequestContext.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponse.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponse.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponse.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponse.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseEntity.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseEntity.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseEntity.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseEntity.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseHeaders.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseHeaders.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseHeaders.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapResponseHeaders.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResult.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResult.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResult.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResult.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultFuture.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultFuture.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultFuture.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultFuture.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultPF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultPF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultPF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultPF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWithPF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWithPF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWithPF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapRouteResultWithPF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapSettings.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapSettings.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapSettings.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapSettings.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapUnmatchedPath.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapUnmatchedPath.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/mapUnmatchedPath.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/mapUnmatchedPath.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/pass.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/pass.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/pass.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/pass.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/provide.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/provide.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/provide.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/provide.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejections.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejections.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejections.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejections.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejectionsWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejectionsWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejectionsWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/recoverRejectionsWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/textract.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/textract.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/textract.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/textract.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/tprovide.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/tprovide.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/tprovide.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/tprovide.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withExecutionContext.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withExecutionContext.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withExecutionContext.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withExecutionContext.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withLog.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withLog.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withLog.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withLog.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withMaterializer.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withMaterializer.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withMaterializer.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withMaterializer.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withSettings.rst b/akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withSettings.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/basic-directives/withSettings.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/basic-directives/withSettings.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/by-trait.rst b/akka-docs/rst/scala/http/routing-dsl/directives/by-trait.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/by-trait.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/by-trait.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cache-condition-directives/conditional.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cache-condition-directives/conditional.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cache-condition-directives/conditional.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cache-condition-directives/conditional.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cache-condition-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cache-condition-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cache-condition-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cache-condition-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequestWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequestWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequestWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/decodeRequestWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponse.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponse.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponse.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponse.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponseWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponseWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponseWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/encodeResponseWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/requestEncodedWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/requestEncodedWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/requestEncodedWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/requestEncodedWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/responseEncodingAccepted.rst b/akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/responseEncodingAccepted.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/coding-directives/responseEncodingAccepted.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/coding-directives/responseEncodingAccepted.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/cookie.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/cookie.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/cookie.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/cookie.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/deleteCookie.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/deleteCookie.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/deleteCookie.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/deleteCookie.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/optionalCookie.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/optionalCookie.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/optionalCookie.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/optionalCookie.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/setCookie.rst b/akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/setCookie.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/cookie-directives/setCookie.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/cookie-directives/setCookie.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/custom-directives.rst b/akka-docs/rst/scala/http/routing-dsl/directives/custom-directives.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/custom-directives.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/custom-directives.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logRequest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logRequest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logRequest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logRequest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logRequestResult.rst b/akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logRequestResult.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logRequestResult.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logRequestResult.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logResult.rst b/akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logResult.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/debugging-directives/logResult.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/debugging-directives/logResult.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/handleExceptions.rst b/akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/handleExceptions.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/handleExceptions.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/handleExceptions.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/handleRejections.rst b/akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/handleRejections.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/handleRejections.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/handleRejections.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/execution-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/execution-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectories.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectories.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectories.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectories.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectory.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectory.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectory.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromBrowseableDirectory.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromDirectory.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromDirectory.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromDirectory.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromDirectory.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromFile.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromFile.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromFile.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromFile.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResource.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResource.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResource.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResource.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResourceDirectory.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResourceDirectory.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResourceDirectory.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/getFromResourceDirectory.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/listDirectoryContents.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/listDirectoryContents.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-and-resource-directives/listDirectoryContents.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-and-resource-directives/listDirectoryContents.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/fileUpload.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/fileUpload.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/fileUpload.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/fileUpload.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/uploadedFile.rst b/akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/uploadedFile.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/file-upload-directives/uploadedFile.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/file-upload-directives/uploadedFile.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/formField.rst b/akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/formField.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/formField.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/formField.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/formFields.rst b/akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/formFields.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/formFields.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/formFields.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/form-field-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/form-field-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/completeOrRecoverWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/future-directives/completeOrRecoverWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/completeOrRecoverWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/future-directives/completeOrRecoverWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/future-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/future-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/onComplete.rst b/akka-docs/rst/scala/http/routing-dsl/directives/future-directives/onComplete.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/onComplete.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/future-directives/onComplete.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/onSuccess.rst b/akka-docs/rst/scala/http/routing-dsl/directives/future-directives/onSuccess.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/future-directives/onSuccess.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/future-directives/onSuccess.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValue.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValue.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValue.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValue.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValueByName.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValueByName.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValueByName.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValueByName.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValueByType.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValueByType.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValueByType.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValueByType.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValuePF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValuePF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/headerValuePF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/headerValuePF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValue.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValue.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValue.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValue.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByName.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByName.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByName.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByName.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByType.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByType.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByType.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValueByType.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValuePF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValuePF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValuePF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/header-directives/optionalHeaderValuePF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/extractHost.rst b/akka-docs/rst/scala/http/routing-dsl/directives/host-directives/extractHost.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/extractHost.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/host-directives/extractHost.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/host.rst b/akka-docs/rst/scala/http/routing-dsl/directives/host-directives/host.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/host.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/host-directives/host.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/host-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/host-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/host-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/completeWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/completeWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/completeWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/completeWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/entity.rst b/akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/entity.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/entity.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/entity.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/handleWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/handleWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/handleWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/handleWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/marshalling-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/marshalling-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/delete.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/delete.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/delete.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/delete.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/extractMethod.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/extractMethod.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/extractMethod.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/extractMethod.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/get.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/get.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/get.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/get.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/head.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/head.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/head.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/head.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/method.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/method.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/method.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/method.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/options.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/options.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/options.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/options.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/overrideMethodWithParameter.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/patch.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/patch.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/patch.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/patch.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/post.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/post.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/post.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/post.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/put.rst b/akka-docs/rst/scala/http/routing-dsl/directives/method-directives/put.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/method-directives/put.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/method-directives/put.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/extractClientIP.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/extractClientIP.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/extractClientIP.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/extractClientIP.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/rejectEmptyResponse.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/rejectEmptyResponse.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/rejectEmptyResponse.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/rejectEmptyResponse.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityEmpty.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityEmpty.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityEmpty.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityEmpty.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityPresent.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityPresent.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityPresent.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/requestEntityPresent.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/selectPreferredLanguage.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/selectPreferredLanguage.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/selectPreferredLanguage.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/selectPreferredLanguage.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/validate.rst b/akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/validate.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/misc-directives/validate.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/misc-directives/validate.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameter.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameter.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameter.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameter.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMap.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMap.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMap.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMap.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMultiMap.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMultiMap.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMultiMap.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterMultiMap.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterSeq.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterSeq.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameterSeq.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameterSeq.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameters.rst b/akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameters.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/parameter-directives/parameters.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/parameter-directives/parameters.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/path.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/path.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/path.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/path.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathEnd.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathEnd.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathEnd.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathEnd.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathEndOrSingleSlash.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathEndOrSingleSlash.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathEndOrSingleSlash.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathEndOrSingleSlash.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathPrefix.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathPrefix.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathPrefix.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathPrefix.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathPrefixTest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathPrefixTest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathPrefixTest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathPrefixTest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSingleSlash.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSingleSlash.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSingleSlash.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSingleSlash.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSuffix.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSuffix.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSuffix.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSuffix.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSuffixTest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSuffixTest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/pathSuffixTest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/pathSuffixTest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefix.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefix.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefix.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefix.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefixTest.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefixTest.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefixTest.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/rawPathPrefixTest.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/redirectToNoTrailingSlashIfPresent.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/redirectToNoTrailingSlashIfPresent.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/redirectToNoTrailingSlashIfPresent.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/redirectToNoTrailingSlashIfPresent.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/redirectToTrailingSlashIfMissing.rst b/akka-docs/rst/scala/http/routing-dsl/directives/path-directives/redirectToTrailingSlashIfMissing.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/path-directives/redirectToTrailingSlashIfMissing.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/path-directives/redirectToTrailingSlashIfMissing.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/range-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/range-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/range-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/range-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/range-directives/withRangeSupport.rst b/akka-docs/rst/scala/http/routing-dsl/directives/range-directives/withRangeSupport.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/range-directives/withRangeSupport.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/range-directives/withRangeSupport.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeader.rst b/akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeader.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeader.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeader.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeaders.rst b/akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeaders.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeaders.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithDefaultHeaders.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeader.rst b/akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeader.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeader.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeader.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeaders.rst b/akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeaders.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeaders.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/respond-with-directives/respondWithHeaders.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/complete.rst b/akka-docs/rst/scala/http/routing-dsl/directives/route-directives/complete.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/complete.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/route-directives/complete.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/failWith.rst b/akka-docs/rst/scala/http/routing-dsl/directives/route-directives/failWith.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/failWith.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/route-directives/failWith.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/route-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/route-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/redirect.rst b/akka-docs/rst/scala/http/routing-dsl/directives/route-directives/redirect.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/redirect.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/route-directives/redirect.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/reject.rst b/akka-docs/rst/scala/http/routing-dsl/directives/route-directives/reject.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/route-directives/reject.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/route-directives/reject.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/extractScheme.rst b/akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/extractScheme.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/extractScheme.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/extractScheme.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/scheme.rst b/akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/scheme.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/scheme-directives/scheme.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/scheme-directives/scheme.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasic.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasic.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasic.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasic.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicAsync.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicAsync.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicAsync.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicAsync.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPFAsync.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPFAsync.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPFAsync.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateBasicPFAsync.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2Async.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2Async.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2Async.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2Async.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PF.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PF.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PF.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PF.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PFAsync.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PFAsync.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PFAsync.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOAuth2PFAsync.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOrRejectWithChallenge.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOrRejectWithChallenge.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authenticateOrRejectWithChallenge.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authenticateOrRejectWithChallenge.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authorize.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authorize.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/authorize.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/authorize.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/extractCredentials.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/extractCredentials.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/extractCredentials.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/extractCredentials.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/security-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/security-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/security-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessages.rst b/akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessages.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessages.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessages.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessagesForProtocol.rst b/akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessagesForProtocol.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessagesForProtocol.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/handleWebsocketMessagesForProtocol.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/index.rst b/akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/directives/websocket-directives/index.rst rename to akka-docs/rst/scala/http/routing-dsl/directives/websocket-directives/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/exception-handling.rst b/akka-docs/rst/scala/http/routing-dsl/exception-handling.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/exception-handling.rst rename to akka-docs/rst/scala/http/routing-dsl/exception-handling.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/index.rst b/akka-docs/rst/scala/http/routing-dsl/index.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/index.rst rename to akka-docs/rst/scala/http/routing-dsl/index.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/overview.rst b/akka-docs/rst/scala/http/routing-dsl/overview.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/overview.rst rename to akka-docs/rst/scala/http/routing-dsl/overview.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/path-matchers.rst b/akka-docs/rst/scala/http/routing-dsl/path-matchers.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/path-matchers.rst rename to akka-docs/rst/scala/http/routing-dsl/path-matchers.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/rejections.rst b/akka-docs/rst/scala/http/routing-dsl/rejections.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/rejections.rst rename to akka-docs/rst/scala/http/routing-dsl/rejections.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/routes.rst b/akka-docs/rst/scala/http/routing-dsl/routes.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/routes.rst rename to akka-docs/rst/scala/http/routing-dsl/routes.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/testkit.rst b/akka-docs/rst/scala/http/routing-dsl/testkit.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/testkit.rst rename to akka-docs/rst/scala/http/routing-dsl/testkit.rst diff --git a/akka-docs-dev/rst/scala/http/routing-dsl/websocket-support.rst b/akka-docs/rst/scala/http/routing-dsl/websocket-support.rst similarity index 100% rename from akka-docs-dev/rst/scala/http/routing-dsl/websocket-support.rst rename to akka-docs/rst/scala/http/routing-dsl/websocket-support.rst diff --git a/akka-docs-dev/rst/scala/stream-index.rst b/akka-docs/rst/scala/stream/index.rst similarity index 74% rename from akka-docs-dev/rst/scala/stream-index.rst rename to akka-docs/rst/scala/stream/index.rst index 8abed2337f..60c7b2f8e0 100644 --- a/akka-docs-dev/rst/scala/stream-index.rst +++ b/akka-docs/rst/scala/stream/index.rst @@ -8,7 +8,7 @@ Streams stream-introduction stream-quickstart - ../stream-design + ../../general/stream/stream-design stream-flows-and-basics stream-graphs stream-composition @@ -19,7 +19,7 @@ Streams stream-io stream-parallelism stream-testkit - ../stages-overview + ../../general/stream/stages-overview stream-cookbook - ../stream-configuration + ../../general/stream/stream-configuration migration-guide-1.0-2.x-scala diff --git a/akka-docs-dev/rst/scala/migration-guide-1.0-2.x-scala.rst b/akka-docs/rst/scala/stream/migration-guide-1.0-2.x-scala.rst similarity index 95% rename from akka-docs-dev/rst/scala/migration-guide-1.0-2.x-scala.rst rename to akka-docs/rst/scala/stream/migration-guide-1.0-2.x-scala.rst index 59f615fafd..6a1413c169 100644 --- a/akka-docs-dev/rst/scala/migration-guide-1.0-2.x-scala.rst +++ b/akka-docs/rst/scala/stream/migration-guide-1.0-2.x-scala.rst @@ -106,7 +106,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#flow-wrap +.. includecode:: ../code/docs/stream/MigrationsScala.scala#flow-wrap and @@ -125,7 +125,7 @@ and Should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#bidiflow-wrap +.. includecode:: ../code/docs/stream/MigrationsScala.scala#bidiflow-wrap FlowGraph class and builder methods have been renamed ===================================================== @@ -160,7 +160,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#graph-create +.. includecode:: ../code/docs/stream/MigrationsScala.scala#graph-create Methods that create Source, Sink, Flow from Graphs have been removed ==================================================================== @@ -217,7 +217,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#graph-create-2 +.. includecode:: ../code/docs/stream/MigrationsScala.scala#graph-create-2 Several Graph builder methods have been removed =============================================== @@ -250,7 +250,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#graph-edges +.. includecode:: ../code/docs/stream/MigrationsScala.scala#graph-edges Source constructor name changes =============================== @@ -302,7 +302,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#source-creators +.. includecode:: ../code/docs/stream/MigrationsScala.scala#source-creators Sink constructor name changes ============================= @@ -325,7 +325,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#sink-creators +.. includecode:: ../code/docs/stream/MigrationsScala.scala#sink-creators ``flatten(FlattenStrategy)`` has been replaced by named counterparts ==================================================================== @@ -349,7 +349,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#flatMapConcat +.. includecode:: ../code/docs/stream/MigrationsScala.scala#flatMapConcat `Sink.fanoutPublisher()` and `Sink.publisher()` is now a single method ====================================================================== @@ -378,7 +378,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#sink-as-publisher +.. includecode:: ../code/docs/stream/MigrationsScala.scala#sink-as-publisher FlexiMerge an FlexiRoute has been replaced by GraphStage ======================================================== @@ -433,7 +433,7 @@ Example This is implemented now as -.. includecode:: code/docs/MigrationsScala.scala#group-flatten +.. includecode:: ../code/docs/stream/MigrationsScala.scala#group-flatten Example 2 ^^^^^^^^^ @@ -452,7 +452,7 @@ Example 2 This is implemented now as -.. includecode:: code/docs/MigrationsScala.scala#group-fold +.. includecode:: ../code/docs/stream/MigrationsScala.scala#group-fold Variance of Inlet and Outlet ============================ @@ -598,7 +598,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#port-async +.. includecode:: ../code/docs/stream/MigrationsScala.scala#port-async Akka HTTP: Uri parsing mode relaxed-with-raw-query replaced with rawQueryString =============================================================================== @@ -628,7 +628,7 @@ Example should be replaced by: -.. includecode:: code/docs/MigrationsScala.scala#raw-query +.. includecode:: ../code/docs/stream/MigrationsScala.scala#raw-query And use of query parameters from ``Uri`` that looked like this: @@ -639,7 +639,7 @@ And use of query parameters from ``Uri`` that looked like this: should be replaced by: -.. includecode:: code/docs/MigrationsScala.scala#query-param +.. includecode:: ../code/docs/stream/MigrationsScala.scala#query-param SynchronousFileSource and SynchronousFileSink ============================================= @@ -673,7 +673,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#file-source-sink +.. includecode:: ../code/docs/stream/MigrationsScala.scala#file-source-sink InputStreamSource and OutputStreamSink ====================================== @@ -703,7 +703,7 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#input-output-stream-source-sink +.. includecode:: ../code/docs/stream/MigrationsScala.scala#input-output-stream-source-sink OutputStreamSource and InputStreamSink ====================================== @@ -736,4 +736,4 @@ Example should be replaced by -.. includecode:: code/docs/MigrationsScala.scala#output-input-stream-source-sink +.. includecode:: ../code/docs/stream/MigrationsScala.scala#output-input-stream-source-sink diff --git a/akka-docs-dev/rst/scala/stream-composition.rst b/akka-docs/rst/scala/stream/stream-composition.rst similarity index 90% rename from akka-docs-dev/rst/scala/stream-composition.rst rename to akka-docs/rst/scala/stream/stream-composition.rst index 592141b384..5760034996 100644 --- a/akka-docs-dev/rst/scala/stream-composition.rst +++ b/akka-docs/rst/scala/stream/stream-composition.rst @@ -17,7 +17,7 @@ we illustrate the most common used stages viewed as "boxes". | -.. image:: ../images/compose_shapes.png +.. image:: ../../images/compose_shapes.png :align: center | @@ -42,7 +42,7 @@ hiding them behind a *shape* that looks like a :class:`Source`, :class:`Flow`, e | -.. image:: ../images/compose_composites.png +.. image:: ../../images/compose_composites.png :align: center | @@ -63,7 +63,7 @@ that is built from a composite :class:`Source` and a composite :class:`Sink` (wh | -.. image:: ../images/compose_nested_flow.png +.. image:: ../../images/compose_nested_flow.png :align: center | @@ -78,7 +78,7 @@ with the rest of the graph), but this demonstrates the uniform underlying model. If we try to build a code snippet that corresponds to the above diagram, our first try might look like this: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#non-nested-flow +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#non-nested-flow It is clear however that there is no nesting present in our first attempt, since the library cannot figure out where we intended to put composite module boundaries, it is our responsibility to do that. If we are using the @@ -87,7 +87,7 @@ methods ``withAttributes()`` or ``named()`` (where the latter is just a shorthan The following code demonstrates how to achieve the desired nesting: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#nested-flow +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#nested-flow Once we have hidden the internals of our components, they act like any other built-in component of similar shape. If we hide some of the internals of our composites, the result looks just like if any other predefine component has been @@ -95,7 +95,7 @@ used: | -.. image:: ../images/compose_nested_flow_opaque.png +.. image:: ../../images/compose_nested_flow_opaque.png :align: center | @@ -103,7 +103,7 @@ used: If we look at usage of built-in components, and our custom components, there is no difference in usage as the code snippet below demonstrates. -.. includecode:: code/docs/stream/CompositionDocSpec.scala#reuse +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#reuse Composing complex systems ------------------------- @@ -119,7 +119,7 @@ As a first example, let's look at a more complex layout: | -.. image:: ../images/compose_graph.png +.. image:: ../../images/compose_graph.png :align: center | @@ -129,13 +129,13 @@ can be materialized) that encapsulates a non-trivial stream processing network. directed and non-directed cycles. The ``runnable()`` method of the :class:`GraphDSL` object allows the creation of a general, closed, and runnable graph. For example the network on the diagram can be realized like this: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#complex-graph +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#complex-graph In the code above we used the implicit port numbering feature (to make the graph more readable and similar to the diagram) and we imported :class:`Source` s, :class:`Sink` s and :class:`Flow` s explicitly. It is possible to refer to the ports explicitly, and it is not necessary to import our linear stages via ``add()``, so another version might look like this: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#complex-graph-alt +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#complex-graph-alt | @@ -146,14 +146,14 @@ from the previous example, what remains is a partial graph: | -.. image:: ../images/compose_graph_partial.png +.. image:: ../../images/compose_graph_partial.png :align: center | We can recreate a similar graph in code, using the DSL in a similar way than before: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#partial-graph +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#partial-graph The only new addition is the return value of the builder block, which is a :class:`Shape`. All graphs (including :class:`Source`, :class:`BidiFlow`, etc) have a shape, which encodes the *typed* ports of the module. In our example @@ -166,14 +166,14 @@ it is a good practice to give names to modules to help debugging. | -.. image:: ../images/compose_graph_shape.png +.. image:: ../../images/compose_graph_shape.png :align: center | Since our partial graph has the right shape, it can be already used in the simpler, linear DSL: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#partial-use +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#partial-use It is not possible to use it as a :class:`Flow` yet, though (i.e. we cannot call ``.filter()`` on it), but :class:`Flow` has a ``wrap()`` method that just adds the DSL to a :class:`FlowShape`. There are similar methods on :class:`Source`, @@ -183,14 +183,14 @@ To demonstrate this, we will create the following graph: | -.. image:: ../images/compose_graph_flow.png +.. image:: ../../images/compose_graph_flow.png :align: center | The code version of the above closed graph might look like this: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#partial-flow-dsl +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#partial-flow-dsl .. note:: All graph builder sections check if the resulting graph has all ports connected except the exposed ones and will @@ -199,7 +199,7 @@ The code version of the above closed graph might look like this: We are still in debt of demonstrating that :class:`RunnableGraph` is a component just like any other, which can be embedded in graphs. In the following snippet we embed one closed graph in another: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#embed-closed +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#embed-closed The type of the imported module indicates that the imported module has a :class:`ClosedShape`, and so we are not able to wire it to anything else inside the enclosing closed graph. Nevertheless, this "island" is embedded properly, @@ -242,7 +242,7 @@ The propagation of the individual materialized values from the enclosed modules | -.. image:: ../images/compose_mat.png +.. image:: ../../images/compose_mat.png :align: center | @@ -251,27 +251,27 @@ To implement the above, first, we create a composite :class:`Source`, where the materialized type of :class:`Promise[Unit]`. By using the combiner function ``Keep.left``, the resulting materialized type is of the nested module (indicated by the color *red* on the diagram): -.. includecode:: code/docs/stream/CompositionDocSpec.scala#mat-combine-1 +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#mat-combine-1 Next, we create a composite :class:`Flow` from two smaller components. Here, the second enclosed :class:`Flow` has a materialized type of :class:`Future[OutgoingConnection]`, and we propagate this to the parent by using ``Keep.right`` as the combiner function (indicated by the color *yellow* on the diagram): -.. includecode:: code/docs/stream/CompositionDocSpec.scala#mat-combine-2 +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#mat-combine-2 As a third step, we create a composite :class:`Sink`, using our ``nestedFlow`` as a building block. In this snippet, both the enclosed :class:`Flow` and the folding :class:`Sink` has a materialized value that is interesting for us, so we use ``Keep.both`` to get a :class:`Pair` of them as the materialized type of ``nestedSink`` (indicated by the color *blue* on the diagram) -.. includecode:: code/docs/stream/CompositionDocSpec.scala#mat-combine-3 +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#mat-combine-3 As the last example, we wire together ``nestedSource`` and ``nestedSink`` and we use a custom combiner function to create a yet another materialized type of the resulting :class:`RunnableGraph`. This combiner function just ignores the :class:`Future[Sink]` part, and wraps the other two values in a custom case class :class:`MyClass` (indicated by color *purple* on the diagram): -.. includecode:: code/docs/stream/CompositionDocSpec.scala#mat-combine-4 +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#mat-combine-4 @@ -293,7 +293,7 @@ unless they override them with a custom value. The code below, a modification of an earlier example sets the ``inputBuffer`` attribute on certain modules, but not on others: -.. includecode:: code/docs/stream/CompositionDocSpec.scala#attributes-inheritance +.. includecode:: ../code/docs/stream/CompositionDocSpec.scala#attributes-inheritance The effect is, that each module inherits the ``inputBuffer`` attribute from its enclosing parent, unless it has the same attribute explicitly set. ``nestedSource`` gets the default attributes from the materializer itself. ``nestedSink`` @@ -302,7 +302,7 @@ except the ``map`` stage which has again an explicitly provided attribute overri | -.. image:: ../images/compose_attributes.png +.. image:: ../../images/compose_attributes.png :align: center | diff --git a/akka-docs-dev/rst/scala/stream-cookbook.rst b/akka-docs/rst/scala/stream/stream-cookbook.rst similarity index 90% rename from akka-docs-dev/rst/scala/stream-cookbook.rst rename to akka-docs/rst/scala/stream/stream-cookbook.rst index 4174f78953..8ec63b1a30 100644 --- a/akka-docs-dev/rst/scala/stream-cookbook.rst +++ b/akka-docs/rst/scala/stream/stream-cookbook.rst @@ -32,12 +32,12 @@ Logging elements of a stream The simplest solution is to simply use a ``map`` operation and use ``println`` to print the elements received to the console. While this recipe is rather simplistic, it is often suitable for a quick debug session. -.. includecode:: code/docs/stream/cookbook/RecipeLoggingElements.scala#println-debug +.. includecode:: ../code/docs/stream/cookbook/RecipeLoggingElements.scala#println-debug Another approach to logging is to use ``log()`` operation which allows configuring logging for elements flowing through the stream as well as completion and erroring. -.. includecode:: code/docs/stream/cookbook/RecipeLoggingElements.scala#log-custom +.. includecode:: ../code/docs/stream/cookbook/RecipeLoggingElements.scala#log-custom Flattening a stream of sequences -------------------------------- @@ -49,7 +49,7 @@ The ``mapConcat`` operation can be used to implement a one-to-many transformatio in the form of ``In => immutable.Seq[Out]``. In this case we want to map a ``Seq`` of elements to the elements in the collection itself, so we can just call ``mapConcat(identity)``. -.. includecode:: code/docs/stream/cookbook/RecipeFlattenSeq.scala#flattening-seqs +.. includecode:: ../code/docs/stream/cookbook/RecipeFlattenSeq.scala#flattening-seqs Draining a stream to a strict collection ---------------------------------------- @@ -63,7 +63,7 @@ with maximum size of ``MaxAllowedSeqSize`` and then we take the first element of :class:`Future` containing a sequence with all the elements of the original up to ``MaxAllowedSeqSize`` size (further elements are dropped). -.. includecode:: code/docs/stream/cookbook/RecipeToStrict.scala#draining-to-seq +.. includecode:: ../code/docs/stream/cookbook/RecipeToStrict.scala#draining-to-seq Calculating the digest of a ByteString stream --------------------------------------------- @@ -83,7 +83,7 @@ we can emit further elements ``onPull`` is called again, and we see ``ctx.isFini source has been depleted already). Since we only want to emit a final element it is enough to call ``ctx.pushAndFinish`` passing the digest ByteString to be emitted. -.. includecode:: code/docs/stream/cookbook/RecipeDigest.scala#calculating-digest +.. includecode:: ../code/docs/stream/cookbook/RecipeDigest.scala#calculating-digest .. _cookbook-parse-lines-scala: @@ -96,7 +96,7 @@ needs to be parsed. The :class:`Framing` helper object contains a convenience method to parse messages from a stream of ``ByteStrings``: -.. includecode:: code/docs/stream/cookbook/RecipeParseLines.scala#parse-lines +.. includecode:: ../code/docs/stream/cookbook/RecipeParseLines.scala#parse-lines Implementing reduce-by-key -------------------------- @@ -126,7 +126,7 @@ any given time. If the ``groupBy`` operator encounters more keys than this number then the stream cannot continue without violating its resource bound, in this case ``groupBy`` will terminate with a failure. -.. includecode:: code/docs/stream/cookbook/RecipeReduceByKey.scala#word-count +.. includecode:: ../code/docs/stream/cookbook/RecipeReduceByKey.scala#word-count By extracting the parts specific to *wordcount* into @@ -136,7 +136,7 @@ By extracting the parts specific to *wordcount* into we get a generalized version below: -.. includecode:: code/docs/stream/cookbook/RecipeReduceByKey.scala#reduce-by-key-general +.. includecode:: ../code/docs/stream/cookbook/RecipeReduceByKey.scala#reduce-by-key-general .. note:: Please note that the reduce-by-key version we discussed above is sequential @@ -157,7 +157,7 @@ To achieve the desired result, we attack the problem in two steps: * Then we take this new stream of message topic pairs (containing a separate pair for each topic a given message belongs to) and feed it into groupBy, using the topic as the group key. -.. includecode:: code/docs/stream/cookbook/RecipeMultiGroupBy.scala#multi-groupby +.. includecode:: ../code/docs/stream/cookbook/RecipeMultiGroupBy.scala#multi-groupby Working with Graphs =================== @@ -174,14 +174,14 @@ trigger signal arrives. This recipe solves the problem by simply zipping the stream of ``Message`` elments with the stream of ``Trigger`` signals. Since ``Zip`` produces pairs, we simply map the output stream selecting the first element of the pair. -.. includecode:: code/docs/stream/cookbook/RecipeManualTrigger.scala#manually-triggered-stream +.. includecode:: ../code/docs/stream/cookbook/RecipeManualTrigger.scala#manually-triggered-stream Alternatively, instead of using a ``Zip``, and then using ``map`` to get the first element of the pairs, we can avoid creating the pairs in the first place by using ``ZipWith`` which takes a two argument function to produce the output element. If this function would return a pair of the two argument it would be exactly the behavior of ``Zip`` so ``ZipWith`` is a generalization of zipping. -.. includecode:: code/docs/stream/cookbook/RecipeManualTrigger.scala#manually-triggered-stream-zipwith +.. includecode:: ../code/docs/stream/cookbook/RecipeManualTrigger.scala#manually-triggered-stream-zipwith .. _cookbook-balance-scala: @@ -199,7 +199,7 @@ The graph consists of a ``Balance`` node which is a special fan-out operation th downstream consumers. In a ``for`` loop we wire all of our desired workers as outputs of this balancer element, then we wire the outputs of these workers to a ``Merge`` element that will collect the results from the workers. -.. includecode:: code/docs/stream/cookbook/RecipeWorkerPool.scala#worker-pool +.. includecode:: ../code/docs/stream/cookbook/RecipeWorkerPool.scala#worker-pool Working with rate ================= @@ -223,7 +223,7 @@ case this is ``identity`` so our folding state starts form the message itself. T special: given the aggregate value (the last message) and the new element (the freshest element) our aggregate state becomes simply the freshest element. This choice of functions results in a simple dropping operation. -.. includecode:: code/docs/stream/cookbook/RecipeSimpleDrop.scala#simple-drop +.. includecode:: ../code/docs/stream/cookbook/RecipeSimpleDrop.scala#simple-drop Dropping broadcast ------------------ @@ -238,7 +238,7 @@ defining a dropping strategy instead of the default ``Backpressure``. This allow between the different consumers (the buffer smooths out small rate variances), but also allows faster consumers to progress by dropping from the buffer of the slow consumers if necessary. -.. includecode:: code/docs/stream/cookbook/RecipeDroppyBroadcast.scala#droppy-bcast +.. includecode:: ../code/docs/stream/cookbook/RecipeDroppyBroadcast.scala#droppy-bcast Collecting missed ticks ----------------------- @@ -258,7 +258,7 @@ We will use ``conflate`` to solve the problem. Conflate takes two functions: As a result, we have a flow of ``Int`` where the number represents the missed ticks. A number 0 means that we were able to consume the tick fast enough (i.e. zero means: 1 non-missed tick + 0 missed ticks) -.. includecode:: code/docs/stream/cookbook/RecipeMissedTicks.scala#missed-ticks +.. includecode:: ../code/docs/stream/cookbook/RecipeMissedTicks.scala#missed-ticks Create a stream processor that repeats the last element seen ------------------------------------------------------------ @@ -276,7 +276,7 @@ to feed the downstream if no upstream element is ready yet. In the ``onPush()`` of ``onPull()``). The downstream ``onPull`` handler is very similar, we immediately relieve the downstream by emitting ``currentValue``. -.. includecode:: code/docs/stream/cookbook/RecipeHold.scala#hold-version-1 +.. includecode:: ../code/docs/stream/cookbook/RecipeHold.scala#hold-version-1 While it is relatively simple, the drawback of the first version is that it needs an arbitrary initial element which is not always possible to provide. Hence, we create a second version where the downstream might need to wait in one single @@ -289,7 +289,7 @@ version is that we call ``holdDownstream()`` if the first element is not yet ava upstream ``onPush()`` handler sets ``waitingFirstValue`` to false, and after checking if ``holdDownstream()`` has been called it either releaves the upstream producer, or both the upstream producer and downstream consumer by calling ``pushAndPull()`` -.. includecode:: code/docs/stream/cookbook/RecipeHold.scala#hold-version-2 +.. includecode:: ../code/docs/stream/cookbook/RecipeHold.scala#hold-version-2 Globally limiting the rate of a set of streams ---------------------------------------------- @@ -310,13 +310,13 @@ of the sender is added to a queue. Once the timer for replenishing the pending p message, we increment the pending permits counter and send a reply to each of the waiting senders. If there are more waiting senders than permits available we will stay in the ``closed`` state. -.. includecode:: code/docs/stream/cookbook/RecipeGlobalRateLimit.scala#global-limiter-actor +.. includecode:: ../code/docs/stream/cookbook/RecipeGlobalRateLimit.scala#global-limiter-actor To create a Flow that uses this global limiter actor we use the ``mapAsync`` function with the combination of the ``ask`` pattern. We also define a timeout, so if a reply is not received during the configured maximum wait period the returned future from ``ask`` will fail, which will fail the corresponding stream as well. -.. includecode:: code/docs/stream/cookbook/RecipeGlobalRateLimit.scala#global-limiter-flow +.. includecode:: ../code/docs/stream/cookbook/RecipeGlobalRateLimit.scala#global-limiter-flow .. note:: The global actor used for limiting introduces a global bottleneck. You might want to assign a dedicated dispatcher @@ -342,7 +342,7 @@ which implements the following logic: Both ``onPush()`` and ``onPull()`` calls ``emitChunkOrPull()`` the only difference is that the push handler also stores the incoming chunk by appending to the end of the buffer. -.. includecode:: code/docs/stream/cookbook/RecipeByteStrings.scala#bytestring-chunker +.. includecode:: ../code/docs/stream/cookbook/RecipeByteStrings.scala#bytestring-chunker Limit the number of bytes passing through a stream of ByteStrings ----------------------------------------------------------------- @@ -354,7 +354,7 @@ This recipe uses a :class:`PushStage` to implement the desired feature. In the o ``onPush()`` we just update a counter and see if it gets larger than ``maximumBytes``. If a violation happens we signal failure, otherwise we forward the chunk we have received. -.. includecode:: code/docs/stream/cookbook/RecipeByteStrings.scala#bytes-limiter +.. includecode:: ../code/docs/stream/cookbook/RecipeByteStrings.scala#bytes-limiter Compact ByteStrings in a stream of ByteStrings ---------------------------------------------- @@ -366,7 +366,7 @@ chain we want to have clean copies that are no longer referencing the original B The recipe is a simple use of map, calling the ``compact()`` method of the :class:`ByteString` elements. This does copying of the underlying arrays, so this should be the last element of a long chain if used. -.. includecode:: code/docs/stream/cookbook/RecipeByteStrings.scala#compacting-bytestrings +.. includecode:: ../code/docs/stream/cookbook/RecipeByteStrings.scala#compacting-bytestrings Injecting keep-alive messages into a stream of ByteStrings ---------------------------------------------------------- @@ -376,4 +376,4 @@ but only if this does not interfere with normal traffic. There is a built-in operation that allows to do this directly: -.. includecode:: code/docs/stream/cookbook/RecipeKeepAlive.scala#inject-keepalive +.. includecode:: ../code/docs/stream/cookbook/RecipeKeepAlive.scala#inject-keepalive diff --git a/akka-docs-dev/rst/scala/stream-customize.rst b/akka-docs/rst/scala/stream/stream-customize.rst similarity index 93% rename from akka-docs-dev/rst/scala/stream-customize.rst rename to akka-docs/rst/scala/stream/stream-customize.rst index 679c9f1ea2..ea3dd17dae 100644 --- a/akka-docs-dev/rst/scala/stream-customize.rst +++ b/akka-docs/rst/scala/stream/stream-customize.rst @@ -29,7 +29,7 @@ As a first motivating example, we will build a new :class:`Source` that will sim cancelled. To start, we need to define the "interface" of our stage, which is called *shape* in Akka Streams terminology (this is explained in more detail in the section :ref:`composition-scala`). This is how this looks like: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#boilerplate-example +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#boilerplate-example As you see, in itself the :class:`GraphStage` only defines the ports of this stage and a shape that contains the ports. It also has, a currently unimplemented method called ``createLogic``. If you recall, stages are reusable in multiple @@ -46,7 +46,7 @@ override ``onPull()`` which indicates that we are free to emit a single element. to stop the stage, we don't need to override it. In the ``onPull`` callback we will simply emit the next number. This is how it looks like in the end: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#custom-source-example +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#custom-source-example Instances of the above :class:`GraphStage` are subclasses of ``Graph[SourceShape[Int],Unit]`` which means that they are already usable in many situations, but do not provide the DSL methods we usually have for other @@ -54,7 +54,7 @@ that they are already usable in many situations, but do not provide the DSL meth ``Source.fromGraph`` (see :ref:`composition-scala` for more details about graphs and DSLs). Now we can use the source as any other built-in one: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#simple-source-usage +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#simple-source-usage Port states, InHandler and OutHandler ------------------------------------- @@ -88,7 +88,7 @@ in that state. | -.. image:: ../images/outport_transitions.png +.. image:: ../../images/outport_transitions.png :align: center | @@ -124,7 +124,7 @@ in that state. | -.. image:: ../images/inport_transitions.png +.. image:: ../../images/inport_transitions.png :align: center | @@ -170,7 +170,7 @@ flowing downstream. | -.. image:: ../images/graph_stage_conceptual.png +.. image:: ../../images/graph_stage_conceptual.png :align: center :width: 500 @@ -181,7 +181,7 @@ To illustrate these concepts we create a small :class:`GraphStage` that implemen | -.. image:: ../images/graph_stage_map.png +.. image:: ../../images/graph_stage_map.png :align: center :width: 300 @@ -190,7 +190,7 @@ To illustrate these concepts we create a small :class:`GraphStage` that implemen Map calls ``push(out)`` from the ``onPush()`` handler and it also calls ``pull()`` from the ``onPull`` handler resulting in the conceptual wiring above, and fully expressed in code below: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#one-to-one +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#one-to-one Map is a typical example of a one-to-one transformation of a stream where demand is passed along upstream elements passed on downstream. @@ -200,7 +200,7 @@ filter. The conceptual wiring of ``Filter`` looks like this: | -.. image:: ../images/graph_stage_filter.png +.. image:: ../../images/graph_stage_filter.png :align: center :width: 300 @@ -212,14 +212,14 @@ we return the “ball” to our upstream so that we get the new element. This is example by adding a conditional in the ``onPush`` handler and decide between a ``pull(in)`` or ``push(out)`` call (and of course not having a mapping ``f`` function). -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#many-to-one +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#many-to-one To complete the picture we define a one-to-many transformation as the next step. We chose a straightforward example stage that emits every upstream element twice downstream. The conceptual wiring of this stage looks like this: | -.. image:: ../images/graph_stage_duplicate.png +.. image:: ../../images/graph_stage_duplicate.png :align: center :width: 300 @@ -229,7 +229,7 @@ This is a stage that has state: an option with the last element it has seen indi has duplicated this last element already or not. We must also make sure to emit the extra element if the upstream completes. -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#one-to-many +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#one-to-many In this case a pull from downstream might be consumed by the stage itself rather than passed along upstream as the stage might contain an element it wants to @@ -242,7 +242,7 @@ This example can be simplified by replacing the usage of a mutable state with ca ``emitMultiple`` which will replace the handlers, emit each of multiple elements and then reinstate the original handlers: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#simpler-one-to-many +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#simpler-one-to-many Finally, to demonstrate all of the stages above, we put them together into a processing chain, @@ -251,7 +251,7 @@ which conceptually would correspond to the following structure: | -.. image:: ../images/graph_stage_chain.png +.. image:: ../../images/graph_stage_chain.png :align: center :width: 700 @@ -259,7 +259,7 @@ which conceptually would correspond to the following structure: In code this is only a few lines, using the ``via`` use our custom stages in a stream: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#graph-stage-chain +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#graph-stage-chain If we attempt to draw the sequence of events, it shows that there is one "event token" in circulation in a potential chain of stages, just like our conceptual "railroad tracks" representation predicts. @@ -267,7 +267,7 @@ in circulation in a potential chain of stages, just like our conceptual "railroa | -.. image:: ../images/graph_stage_tracks_1.png +.. image:: ../../images/graph_stage_tracks_1.png :align: center :width: 700 @@ -305,7 +305,7 @@ In this sample the stage toggles between open and closed, where open means no el stage starts out as closed but as soon as an element is pushed downstream the gate becomes open for a duration of time during which it will consume and drop upstream messages: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#timed +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#timed Using asynchronous side-channels @@ -325,7 +325,7 @@ Sharing the AsyncCallback from the constructor risks race conditions, therefore This example shows an asynchronous side channel graph stage that starts dropping elements when a future completes: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#async-side-channel +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#async-side-channel Integration with actors ----------------------- @@ -361,7 +361,7 @@ stage logic the materialized value must be provided In this sample the materialized value is a future containing the first element to go through the stream: -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#materialized +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#materialized Using attributes to affect the behavior of a stage @@ -400,7 +400,7 @@ is seen from downstream. | -.. image:: ../images/graph_stage_detached_tracks_1.png +.. image:: ../../images/graph_stage_detached_tracks_1.png :align: center :width: 500 @@ -412,7 +412,7 @@ into the buffer stage. | -.. image:: ../images/graph_stage_detached_tracks_2.png +.. image:: ../../images/graph_stage_detached_tracks_2.png :align: center :width: 500 @@ -424,7 +424,7 @@ initialization. The buffer has demand for up to two elements without any downstr The following code example demonstrates a buffer class corresponding to the message sequence chart above. -.. includecode:: code/docs/stream/GraphStageDocSpec.scala#detached +.. includecode:: ../code/docs/stream/GraphStageDocSpec.scala#detached Thread safety of custom processing stages diff --git a/akka-docs-dev/rst/scala/stream-error.rst b/akka-docs/rst/scala/stream/stream-error.rst similarity index 82% rename from akka-docs-dev/rst/scala/stream-error.rst rename to akka-docs/rst/scala/stream/stream-error.rst index 760e1cb868..6333d447dc 100644 --- a/akka-docs-dev/rst/scala/stream-error.rst +++ b/akka-docs/rst/scala/stream/stream-error.rst @@ -28,11 +28,11 @@ There are three ways to handle exceptions from application code: By default the stopping strategy is used for all exceptions, i.e. the stream will be completed with failure when an exception is thrown. -.. includecode:: code/docs/stream/FlowErrorDocSpec.scala#stop +.. includecode:: ../code/docs/stream/FlowErrorDocSpec.scala#stop The default supervision strategy for a stream can be defined on the settings of the materializer. -.. includecode:: code/docs/stream/FlowErrorDocSpec.scala#resume +.. includecode:: ../code/docs/stream/FlowErrorDocSpec.scala#resume Here you can see that all ``ArithmeticException`` will resume the processing, i.e. the elements that cause the division by zero are effectively dropped. @@ -44,12 +44,12 @@ elements that cause the division by zero are effectively dropped. The supervision strategy can also be defined for all operators of a flow. -.. includecode:: code/docs/stream/FlowErrorDocSpec.scala#resume-section +.. includecode:: ../code/docs/stream/FlowErrorDocSpec.scala#resume-section ``Restart`` works in a similar way as ``Resume`` with the addition that accumulated state, if any, of the failing processing stage will be reset. -.. includecode:: code/docs/stream/FlowErrorDocSpec.scala#restart-section +.. includecode:: ../code/docs/stream/FlowErrorDocSpec.scala#restart-section Errors from mapAsync ==================== @@ -61,11 +61,11 @@ discard those that cannot be found. We start with the tweet stream of authors: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#tweet-authors +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#tweet-authors Assume that we can lookup their email address using: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#email-address-lookup2 +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#email-address-lookup2 The ``Future`` is completed with ``Failure`` if the email is not found. @@ -73,7 +73,7 @@ Transforming the stream of authors to a stream of email addresses by using the ` service can be done with ``mapAsync`` and we use ``Supervision.resumingDecider`` to drop unknown email addresses: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#email-addresses-mapAsync-supervision +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#email-addresses-mapAsync-supervision If we would not use ``Resume`` the default stopping strategy would complete the stream with failure on the first ``Future`` that was completed with ``Failure``. diff --git a/akka-docs-dev/rst/scala/stream-flows-and-basics.rst b/akka-docs/rst/scala/stream/stream-flows-and-basics.rst similarity index 96% rename from akka-docs-dev/rst/scala/stream-flows-and-basics.rst rename to akka-docs/rst/scala/stream/stream-flows-and-basics.rst index 285618b5c3..c9c6864b8c 100644 --- a/akka-docs-dev/rst/scala/stream-flows-and-basics.rst +++ b/akka-docs/rst/scala/stream/stream-flows-and-basics.rst @@ -76,7 +76,7 @@ starting up Actors). Thanks to Flows being simply a description of the processin thread-safe, and freely shareable*, which means that it is for example safe to share and send them between actors, to have one actor prepare the work, and then have it be materialized at some completely different place in the code. -.. includecode:: code/docs/stream/FlowDocSpec.scala#materialization-in-steps +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#materialization-in-steps After running (materializing) the ``RunnableGraph[T]`` we get back the materialized value of type T. Every stream processing stage can produce a materialized value, and it is the responsibility of the user to combine them to a new type. @@ -90,12 +90,12 @@ there is a convenience method called ``runWith()`` available for ``Sink``, ``Sou a supplied ``Source`` (in order to run a ``Sink``), a ``Sink`` (in order to run a ``Source``) or both a ``Source`` and a ``Sink`` (in order to run a ``Flow``, since it has neither attached yet). -.. includecode:: code/docs/stream/FlowDocSpec.scala#materialization-runWith +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#materialization-runWith It is worth pointing out that since processing stages are *immutable*, connecting them returns a new processing stage, instead of modifying the existing instance, so while constructing long flows, remember to assign the new value to a variable or run it: -.. includecode:: code/docs/stream/FlowDocSpec.scala#source-immutable +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#source-immutable .. note:: By default Akka Streams elements support **exactly one** downstream processing stage. @@ -112,7 +112,7 @@ In the example below we create two running materialized instance of the stream t variable, and both materializations give us a different ``Future`` from the map even though we used the same ``sink`` to refer to the future: -.. includecode:: code/docs/stream/FlowDocSpec.scala#stream-reuse +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#stream-reuse Defining sources, sinks and flows --------------------------------- @@ -120,11 +120,11 @@ Defining sources, sinks and flows The objects :class:`Source` and :class:`Sink` define various ways to create sources and sinks of elements. The following examples show some of the most useful constructs (refer to the API documentation for more details): -.. includecode:: code/docs/stream/FlowDocSpec.scala#source-sink +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#source-sink There are various ways to wire up different parts of a stream, the following examples show some of the available options: -.. includecode:: code/docs/stream/FlowDocSpec.scala#flow-connecting +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#flow-connecting Illegal stream elements ----------------------- @@ -242,13 +242,13 @@ consequences: The first point can be countered by pre-fusing and then reusing a stream blueprint as sketched below: -.. includecode:: code/docs/stream/FlowDocSpec.scala#explicit-fusing +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#explicit-fusing In order to balance the effects of the second and third bullet points you will have to insert asynchronous boundaries manually into your flows and graphs by way of adding ``Attributes.asyncBoundary`` to pieces that shall communicate with the rest of the graph in an asynchronous fashion. -.. includecode:: code/docs/stream/FlowDocSpec.scala#flow-async +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#flow-async In this example we create two regions within the flow which will be executed in one Actor each—assuming that adding and multiplying integers is an extremely costly operation this will lead to a performance gain since two CPUs can @@ -258,7 +258,7 @@ by adding information to the flow graph that has been constructed up to this poi | -.. image:: ../images/asyncBoundary.png +.. image:: ../../images/asyncBoundary.png :align: center :width: 700 @@ -291,7 +291,7 @@ to somehow express how these values should be composed to a final value when we many combinator methods have variants that take an additional argument, a function, that will be used to combine the resulting values. Some examples of using these combiners are illustrated in the example below. -.. includecode:: code/docs/stream/FlowDocSpec.scala#flow-mat-combine +.. includecode:: ../code/docs/stream/FlowDocSpec.scala#flow-mat-combine .. note:: diff --git a/akka-docs-dev/rst/scala/stream-graphs.rst b/akka-docs/rst/scala/stream/stream-graphs.rst similarity index 91% rename from akka-docs-dev/rst/scala/stream-graphs.rst rename to akka-docs/rst/scala/stream/stream-graphs.rst index 4f6f77e273..314298904b 100644 --- a/akka-docs-dev/rst/scala/stream-graphs.rst +++ b/akka-docs/rst/scala/stream/stream-graphs.rst @@ -45,14 +45,14 @@ One of the goals of the GraphDSL DSL is to look similar to how one would draw a simple to translate a design from whiteboard to code and be able to relate those two. Let's illustrate this by translating the below hand drawn graph into Akka Streams: -.. image:: ../images/simple-graph-example.png +.. image:: ../../images/simple-graph-example.png Such graph is simple to translate to the Graph DSL since each linear element corresponds to a :class:`Flow`, and each circle corresponds to either a :class:`Junction` or a :class:`Source` or :class:`Sink` if it is beginning or ending a :class:`Flow`. Junctions must always be created with defined type parameters, as otherwise the ``Nothing`` type will be inferred. -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#simple-flow-graph +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#simple-flow-graph .. note:: Junction *reference equality* defines *graph node equality* (i.e. the same merge *instance* used in a GraphDSL @@ -80,7 +80,7 @@ In the example below we prepare a graph that consists of two parallel streams, in which we re-use the same instance of :class:`Flow`, yet it will properly be materialized as two connections between the corresponding Sources and Sinks: -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-reusing-a-flow +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-reusing-a-flow .. _partial-flow-graph-scala: @@ -103,7 +103,7 @@ Let's imagine we want to provide users with a specialized element that given 3 i the greatest int value of each zipped triple. We'll want to expose 3 input ports (unconnected sources) and one output port (unconnected sink). -.. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#simple-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocSpec.scala#simple-partial-flow-graph As you can see, first we construct the partial graph that contains all the zipping and comparing of stream elements. This partial graph will have three inputs and one output, wherefore we use the :class:`UniformFanInShape`. @@ -143,12 +143,12 @@ from the function passed in . The single outlet must be provided to the ``Source Refer to the example below, in which we create a Source that zips together two numbers, to see this graph construction in action: -.. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#source-from-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocSpec.scala#source-from-partial-flow-graph Similarly the same can be done for a ``Sink[T]``, using ``SinkShape.of`` in which case the provided value must be an ``Inlet[T]``. For defining a ``Flow[T]`` we need to expose both an inlet and an outlet: -.. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#flow-from-partial-flow-graph +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocSpec.scala#flow-from-partial-flow-graph Combining Sources and Sinks with simplified API ----------------------------------------------- @@ -157,11 +157,11 @@ There is a simplified API you can use to combine sources and sinks with junction ``Merge[In]`` and ``Concat[A]`` without the need for using the Graph DSL. The combine method takes care of constructing the necessary graph underneath. In following example we combine two sources into one (fan-in): -.. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#source-combine +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocSpec.scala#source-combine The same can be done for a ``Sink[T]`` but in this case it will be fan-out: -.. includecode:: code/docs/stream/StreamPartialFlowGraphDocSpec.scala#sink-combine +.. includecode:: ../code/docs/stream/StreamPartialFlowGraphDocSpec.scala#sink-combine Building reusable Graph components ---------------------------------- @@ -178,7 +178,7 @@ where jobs of higher priority can be sent. Altogether, our junction will have two input ports of type ``I`` (for the normal and priority jobs) and an output port of type ``O``. To represent this interface, we need to define a custom :class:`Shape`. The following lines show how to do that. -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-shape +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-shape .. _predefined-shapes: @@ -198,20 +198,20 @@ boilerplate: Since our shape has two input ports and one output port, we can just use the :class:`FanInShape` DSL to define our custom shape: -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-shape2 +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-shape2 Now that we have a :class:`Shape` we can wire up a Graph that represents our worker pool. First, we will merge incoming normal and priority jobs using ``MergePreferred``, then we will send the jobs to a ``Balance`` junction which will fan-out to a configurable number of workers (flows), finally we merge all these results together and send them out through our only output port. This is expressed by the following code: -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-create +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-create All we need to do now is to use our custom junction in a graph. The following code simulates some simple workers and jobs using plain strings and prints out the results. Actually we used *two* instances of our worker pool junction using ``add()`` twice. -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-use +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-components-use .. _bidi-flow-scala: @@ -228,14 +228,14 @@ this purpose exists the special type :class:`BidiFlow` which is a graph that has exactly two open inlets and two open outlets. The corresponding shape is called :class:`BidiShape` and is defined like this: -.. includecode:: ../../../akka-stream/src/main/scala/akka/stream/Shape.scala +.. includecode:: ../../../../akka-stream/src/main/scala/akka/stream/Shape.scala :include: bidi-shape :exclude: implementation-details-elided A bidirectional flow is defined just like a unidirectional :class:`Flow` as demonstrated for the codec mentioned above: -.. includecode:: code/docs/stream/BidiFlowDocSpec.scala +.. includecode:: ../code/docs/stream/BidiFlowDocSpec.scala :include: codec :exclude: implementation-details-elided @@ -244,7 +244,7 @@ case of a functional 1:1 transformation there is a concise convenience method as shown on the last line. The implementation of the two functions is not difficult either: -.. includecode:: code/docs/stream/BidiFlowDocSpec.scala#codec-impl +.. includecode:: ../code/docs/stream/BidiFlowDocSpec.scala#codec-impl In this way you could easily integrate any other serialization library that turns an object into a sequence of bytes. @@ -254,11 +254,11 @@ a framing protocol means that any received chunk of bytes may correspond to zero or more messages. This is best implemented using a :class:`GraphStage` (see also :ref:`graphstage-scala`). -.. includecode:: code/docs/stream/BidiFlowDocSpec.scala#framing +.. includecode:: ../code/docs/stream/BidiFlowDocSpec.scala#framing With these implementations we can build a protocol stack and test it: -.. includecode:: code/docs/stream/BidiFlowDocSpec.scala#compose +.. includecode:: ../code/docs/stream/BidiFlowDocSpec.scala#compose This example demonstrates how :class:`BidiFlow` subgraphs can be hooked together and also turned around with the ``.reversed`` method. The test @@ -276,12 +276,12 @@ can be used in the graph as an ordinary source or outlet, and which will eventua If the materialized value is needed at more than one place, it is possible to call ``materializedValue`` any number of times to acquire the necessary number of outlets. -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-matvalue +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-matvalue Be careful not to introduce a cycle where the materialized value actually contributes to the materialized value. The following example demonstrates a case where the materialized ``Future`` of a fold is fed back to the fold itself. -.. includecode:: code/docs/stream/FlowGraphDocSpec.scala#flow-graph-matvalue-cycle +.. includecode:: ../code/docs/stream/FlowGraphDocSpec.scala#flow-graph-matvalue-cycle .. _graph-cycles-scala: @@ -302,7 +302,7 @@ a ``Merge`` junction. The graph DSL allows the connection arrows to be reversed, which is particularly handy when writing cycles—as we will see there are cases where this is very helpful. -.. includecode:: code/docs/stream/GraphCyclesSpec.scala#deadlocked +.. includecode:: ../code/docs/stream/GraphCyclesSpec.scala#deadlocked Running this we observe that after a few numbers have been printed, no more elements are logged to the console - all processing stops after some time. After some investigation we observe that: @@ -320,7 +320,7 @@ If we modify our feedback loop by replacing the ``Merge`` junction with a ``Merg before trying the other lower priority input ports. Since we feed back through the preferred port it is always guaranteed that the elements in the cycles can flow. -.. includecode:: code/docs/stream/GraphCyclesSpec.scala#unfair +.. includecode:: ../code/docs/stream/GraphCyclesSpec.scala#unfair If we run the example we see that the same sequence of numbers are printed over and over again, but the processing does not stop. Hence, we avoided the deadlock, but ``source`` is still @@ -335,7 +335,7 @@ of initial elements from ``source``. To make our cycle both live (not deadlocking) and fair we can introduce a dropping element on the feedback arc. In this case we chose the ``buffer()`` operation giving it a dropping strategy ``OverflowStrategy.dropHead``. -.. includecode:: code/docs/stream/GraphCyclesSpec.scala#dropping +.. includecode:: ../code/docs/stream/GraphCyclesSpec.scala#dropping If we run this example we see that @@ -354,7 +354,7 @@ the beginning instead. To achieve this we modify our first graph by replacing th Since ``ZipWith`` takes one element from ``source`` *and* from the feedback arc to inject one element into the cycle, we maintain the balance of elements. -.. includecode:: code/docs/stream/GraphCyclesSpec.scala#zipping-dead +.. includecode:: ../code/docs/stream/GraphCyclesSpec.scala#zipping-dead Still, when we try to run the example it turns out that no element is printed at all! After some investigation we realize that: @@ -366,7 +366,7 @@ These two conditions are a typical "chicken-and-egg" problem. The solution is to element into the cycle that is independent from ``source``. We do this by using a ``Concat`` junction on the backwards arc that injects a single element using ``Source.single``. -.. includecode:: code/docs/stream/GraphCyclesSpec.scala#zipping-live +.. includecode:: ../code/docs/stream/GraphCyclesSpec.scala#zipping-live When we run the above example we see that processing starts and never stops. The important takeaway from this example is that balanced cycles often need an initial "kick-off" element to be injected into the cycle. diff --git a/akka-docs-dev/rst/scala/stream-integrations.rst b/akka-docs/rst/scala/stream/stream-integrations.rst similarity index 87% rename from akka-docs-dev/rst/scala/stream-integrations.rst rename to akka-docs/rst/scala/stream/stream-integrations.rst index ba63fcd1f4..d1a858b113 100644 --- a/akka-docs-dev/rst/scala/stream-integrations.rst +++ b/akka-docs/rst/scala/stream/stream-integrations.rst @@ -68,7 +68,7 @@ stream publisher that keeps track of the subscription life cycle and requested e Here is an example of such an actor. It dispatches incoming jobs to the attached subscriber: -.. includecode:: code/docs/stream/ActorPublisherDocSpec.scala#job-manager +.. includecode:: ../code/docs/stream/ActorPublisherDocSpec.scala#job-manager You send elements to the stream by calling ``onNext``. You are allowed to send as many elements as have been requested by the stream subscriber. This amount can be inquired with @@ -100,7 +100,7 @@ More detailed information can be found in the API documentation. This is how it can be used as input :class:`Source` to a :class:`Flow`: -.. includecode:: code/docs/stream/ActorPublisherDocSpec.scala#actor-publisher-usage +.. includecode:: ../code/docs/stream/ActorPublisherDocSpec.scala#actor-publisher-usage A publisher that is created with ``Sink.asPublisher`` supports a specified number of subscribers. Additional subscription attempts will be rejected with an :class:`IllegalStateException`. @@ -115,7 +115,7 @@ messages from the stream. It can also receive other, non-stream messages, in the Here is an example of such an actor. It dispatches incoming jobs to child worker actors: -.. includecode:: code/docs/stream/ActorSubscriberDocSpec.scala#worker-pool +.. includecode:: ../code/docs/stream/ActorSubscriberDocSpec.scala#worker-pool Subclass must define the ``RequestStrategy`` to control stream back pressure. After each incoming message the ``ActorSubscriber`` will automatically invoke @@ -133,7 +133,7 @@ More detailed information can be found in the API documentation. This is how it can be used as output :class:`Sink` to a :class:`Flow`: -.. includecode:: code/docs/stream/ActorSubscriberDocSpec.scala#actor-subscriber-usage +.. includecode:: ../code/docs/stream/ActorSubscriberDocSpec.scala#actor-subscriber-usage Integrating with External Services ================================== @@ -144,24 +144,24 @@ performed with ``mapAsync`` or ``mapAsyncUnordered``. For example, sending emails to the authors of selected tweets using an external email service: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#email-server-send +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#email-server-send We start with the tweet stream of authors: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#tweet-authors +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#tweet-authors Assume that we can lookup their email address using: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#email-address-lookup +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#email-address-lookup Transforming the stream of authors to a stream of email addresses by using the ``lookupEmail`` service can be done with ``mapAsync``: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#email-addresses-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#email-addresses-mapAsync Finally, sending the emails: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#send-emails +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#send-emails ``mapAsync`` is applying the given function that is calling out to the external service to each of the elements as they pass through this processing step. The function returns a :class:`Future` @@ -183,23 +183,23 @@ result stream onwards for further processing or storage. Note that ``mapAsync`` preserves the order of the stream elements. In this example the order is not important and then we can use the more efficient ``mapAsyncUnordered``: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#external-service-mapAsyncUnordered +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#external-service-mapAsyncUnordered In the above example the services conveniently returned a :class:`Future` of the result. If that is not the case you need to wrap the call in a :class:`Future`. If the service call involves blocking you must also make sure that you run it on a dedicated execution context, to avoid starvation and disturbance of other tasks in the system. -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#blocking-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#blocking-mapAsync The configuration of the ``"blocking-dispatcher"`` may look something like: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#blocking-dispatcher-config +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#blocking-dispatcher-config An alternative for blocking calls is to perform them in a ``map`` operation, still using a dedicated dispatcher for that operation. -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#blocking-map +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#blocking-map However, that is not exactly the same as ``mapAsync``, since the ``mapAsync`` may run several calls concurrently, but ``map`` performs them one at a time. @@ -207,7 +207,7 @@ several calls concurrently, but ``map`` performs them one at a time. For a service that is exposed as an actor, or if an actor is used as a gateway in front of an external service, you can use ``ask``: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#save-tweets +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#save-tweets Note that if the ``ask`` is not completed within the given timeout the stream is completed with failure. If that is not desired outcome you can use ``recover`` on the ``ask`` :class:`Future`. @@ -236,14 +236,14 @@ successive calls as long as there is downstream demand of several elements. Here is a fictive service that we can use to illustrate these aspects. -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-service +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-service Elements starting with a lower case character are simulated to take longer time to process. Here is how we can use it with ``mapAsync``: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-mapAsync +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-mapAsync The output may look like this: @@ -300,7 +300,7 @@ calls are limited by the buffer size (4) of the :class:`ActorMaterializerSetting Here is how we can use the same service with ``mapAsyncUnordered``: -.. includecode:: code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-mapAsyncUnordered +.. includecode:: ../code/docs/stream/IntegrationDocSpec.scala#sometimes-slow-mapAsyncUnordered The output may look like this: @@ -378,19 +378,19 @@ An incomplete list of other implementations: The two most important interfaces in Reactive Streams are the :class:`Publisher` and :class:`Subscriber`. -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#imports +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#imports Let us assume that a library provides a publisher of tweets: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#tweets-publisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#tweets-publisher and another library knows how to store author handles in a database: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#author-storage-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#author-storage-subscriber Using an Akka Streams :class:`Flow` we can transform the stream and connect those: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala :include: authors,connect-all The :class:`Publisher` is used as an input :class:`Source` to the flow and the @@ -400,24 +400,24 @@ A :class:`Flow` can also be also converted to a :class:`RunnableGraph[Processor[ materializes to a :class:`Processor` when ``run()`` is called. ``run()`` itself can be called multiple times, resulting in a new :class:`Processor` instance each time. -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#flow-publisher-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#flow-publisher-subscriber A publisher can be connected to a subscriber with the ``subscribe`` method. It is also possible to expose a :class:`Source` as a :class:`Publisher` by using the Publisher-:class:`Sink`: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#source-publisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#source-publisher A publisher that is created with ``Sink.asPublisher(false)`` supports only a single subscription. Additional subscription attempts will be rejected with an :class:`IllegalStateException`. A publisher that supports multiple subscribers using fan-out/broadcasting is created as follows: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala :include: author-alert-subscriber,author-storage-subscriber -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#source-fanoutPublisher +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#source-fanoutPublisher The input buffer size of the stage controls how far apart the slowest subscriber can be from the fastest subscriber before slowing down the stream. @@ -425,11 +425,11 @@ before slowing down the stream. To make the picture complete, it is also possible to expose a :class:`Sink` as a :class:`Subscriber` by using the Subscriber-:class:`Source`: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#sink-subscriber +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#sink-subscriber It is also possible to use re-wrap :class:`Processor` instances as a :class:`Flow` by passing a factory function that will create the :class:`Processor` instances: -.. includecode:: code/docs/stream/ReactiveStreamsDocSpec.scala#use-processor +.. includecode:: ../code/docs/stream/ReactiveStreamsDocSpec.scala#use-processor Please note that a factory is necessary to achieve reusability of the resulting :class:`Flow`. diff --git a/akka-docs-dev/rst/scala/stream-introduction.rst b/akka-docs/rst/scala/stream/stream-introduction.rst similarity index 100% rename from akka-docs-dev/rst/scala/stream-introduction.rst rename to akka-docs/rst/scala/stream/stream-introduction.rst diff --git a/akka-docs-dev/rst/scala/stream-io.rst b/akka-docs/rst/scala/stream/stream-io.rst similarity index 93% rename from akka-docs-dev/rst/scala/stream-io.rst rename to akka-docs/rst/scala/stream/stream-io.rst index 5b8352a8b4..bb59479a04 100644 --- a/akka-docs-dev/rst/scala/stream-io.rst +++ b/akka-docs/rst/scala/stream/stream-io.rst @@ -19,7 +19,7 @@ Accepting connections: Echo Server In order to implement a simple EchoServer we ``bind`` to a given address, which returns a ``Source[IncomingConnection, Future[ServerBinding]]``, which will emit an :class:`IncomingConnection` element for each new connection that the Server should handle: -.. includecode:: code/docs/stream/io/StreamTcpDocSpec.scala#echo-server-simple-bind +.. includecode:: ../code/docs/stream/io/StreamTcpDocSpec.scala#echo-server-simple-bind Next, we simply handle *each* incoming connection using a :class:`Flow` which will be used as the processing stage to handle and emit ByteStrings from and to the TCP Socket. Since one :class:`ByteString` does not have to necessarily @@ -28,7 +28,7 @@ helper Flow to chunk the inputs up into actual lines of text. The last boolean argument indicates that we require an explicit line ending even for the last message before the connection is closed. In this example we simply add exclamation marks to each incoming text message and push it through the flow: -.. includecode:: code/docs/stream/io/StreamTcpDocSpec.scala#echo-server-simple-handle +.. includecode:: ../code/docs/stream/io/StreamTcpDocSpec.scala#echo-server-simple-handle Notice that while most building blocks in Akka Streams are reusable and freely shareable, this is *not* the case for the incoming connection Flow, since it directly corresponds to an existing, already accepted connection its handling can @@ -52,7 +52,7 @@ Let's say we know a server has exposed a simple command line interface over TCP, and would like to interact with it using Akka Streams over TCP. To open an outgoing connection socket we use the ``outgoingConnection`` method: -.. includecode:: code/docs/stream/io/StreamTcpDocSpec.scala#repl-client +ąio/StreamTcpDocSpec.scala#repl-client The ``repl`` flow we use to handle the server interaction first prints the servers response, then awaits on input from the command line (this blocking call is used here just for the sake of simplicity) and converts it to a @@ -84,7 +84,7 @@ Thankfully in most situations finding the right spot to start the conversation i to the protocol we are trying to implement using Streams. In chat-like applications, which our examples resemble, it makes sense to make the Server initiate the conversation by emitting a "hello" message: -.. includecode:: code/docs/stream/io/StreamTcpDocSpec.scala#welcome-banner-chat-server +.. includecode:: ../code/docs/stream/io/StreamTcpDocSpec.scala#welcome-banner-chat-server The way we constructed a :class:`Flow` using the :class:`GraphDSL` is explained in detail in :ref:`constructing-sources-sinks-flows-from-partial-graphs-scala`, however the basic concepts is rather simple– @@ -113,7 +113,7 @@ on files. Streaming data from a file is as easy as creating a `FileIO.fromFile` given a target file, and an optional ``chunkSize`` which determines the buffer size determined as one "element" in such stream: -.. includecode:: code/docs/stream/io/StreamFileDocSpec.scala#file-source +.. includecode:: ../code/docs/stream/io/StreamFileDocSpec.scala#file-source Please note that these processing stages are backed by Actors and by default are configured to run on a pre-configured threadpool-backed dispatcher dedicated for File IO. This is very important as it isolates the blocking file IO operations from the rest @@ -121,4 +121,4 @@ of the ActorSystem allowing each dispatcher to be utilised in the most efficient dispatcher for file IO operations globally, you can do so by changing the ``akka.stream.blocking-io-dispatcher``, or for a specific stage by specifying a custom Dispatcher in code, like this: -.. includecode:: code/docs/stream/io/StreamFileDocSpec.scala#custom-dispatcher-code +.. includecode:: ../code/docs/stream/io/StreamFileDocSpec.scala#custom-dispatcher-code diff --git a/akka-docs-dev/rst/scala/stream-parallelism.rst b/akka-docs/rst/scala/stream/stream-parallelism.rst similarity index 94% rename from akka-docs-dev/rst/scala/stream-parallelism.rst rename to akka-docs/rst/scala/stream/stream-parallelism.rst index 84969dbec3..c48de591f7 100644 --- a/akka-docs-dev/rst/scala/stream-parallelism.rst +++ b/akka-docs/rst/scala/stream/stream-parallelism.rst @@ -23,7 +23,7 @@ are two pancakes being cooked at the same time, one being cooked on its first si completion. This is how this setup would look like implemented as a stream: -.. includecode:: code/docs/stream/FlowParallelismDocSpec.scala#pipelining +.. includecode:: ../code/docs/stream/FlowParallelismDocSpec.scala#pipelining The two ``map`` stages in sequence (encapsulated in the "frying pan" flows) will be executed in a pipelined way, basically doing the same as Roland with his frying pans: @@ -51,7 +51,7 @@ the results on a shared plate. Whenever a pan becomes empty, he takes the next s In essence he parallelizes the same process over multiple pans. This is how this setup will look like if implemented using streams: -.. includecode:: code/docs/stream/FlowParallelismDocSpec.scala#parallelism +.. includecode:: ../code/docs/stream/FlowParallelismDocSpec.scala#parallelism The benefit of parallelizing is that it is easy to scale. In the pancake example it is easy to add a third frying pan with Patrik's method, but Roland cannot add a third frying pan, @@ -74,7 +74,7 @@ First, let's look at how we can parallelize pipelined processing stages. In the will employ two chefs, each working using Roland's pipelining method, but we use the two chefs in parallel, just like Patrik used the two frying pans. This is how it looks like if expressed as streams: -.. includecode:: code/docs/stream/FlowParallelismDocSpec.scala#parallel-pipeline +.. includecode:: ../code/docs/stream/FlowParallelismDocSpec.scala#parallel-pipeline The above pattern works well if there are many independent jobs that do not depend on the results of each other, but the jobs themselves need multiple processing steps where each step builds on the result of @@ -91,7 +91,7 @@ It is also possible to organize parallelized stages into pipelines. This would m This is again straightforward to implement with the streams API: -.. includecode:: code/docs/stream/FlowParallelismDocSpec.scala#pipelined-parallel +.. includecode:: ../code/docs/stream/FlowParallelismDocSpec.scala#pipelined-parallel This usage pattern is less common but might be usable if a certain step in the pipeline might take wildly different times to finish different jobs. The reason is that there are more balance-merge steps in this pattern diff --git a/akka-docs-dev/rst/scala/stream-quickstart.rst b/akka-docs/rst/scala/stream/stream-quickstart.rst similarity index 89% rename from akka-docs-dev/rst/scala/stream-quickstart.rst rename to akka-docs/rst/scala/stream/stream-quickstart.rst index 2bea600bdf..7b1abdcf92 100644 --- a/akka-docs-dev/rst/scala/stream-quickstart.rst +++ b/akka-docs/rst/scala/stream/stream-quickstart.rst @@ -15,7 +15,7 @@ allow to control what should happen in such scenarios. Here's the data model we'll be working with throughout the quickstart examples: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#model +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#model .. note:: If you would like to get an overview of the used vocabulary first instead of diving head-first @@ -30,7 +30,7 @@ like for example finding all twitter handles of users who tweet about ``#akka``. In order to prepare our environment by creating an :class:`ActorSystem` and :class:`ActorMaterializer`, which will be responsible for materializing and running the streams we are about to create: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#materializer-setup +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#materializer-setup The :class:`ActorMaterializer` can optionally take :class:`ActorMaterializerSettings` which can be used to define materialization properties, such as default buffer sizes (see also :ref:`stream-buffers-scala`), the dispatcher to @@ -38,7 +38,7 @@ be used by the pipeline etc. These can be overridden with ``withAttributes`` on Let's assume we have a stream of tweets readily available. In Akka this is expressed as a :class:`Source[Out, M]`: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweet-source +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweet-source Streams always start flowing from a :class:`Source[Out,M1]` then can continue through :class:`Flow[In,Out,M2]` elements or more advanced graph elements to finally be consumed by a :class:`Sink[In,M3]` (ignore the type parameters ``M1``, ``M2`` @@ -49,7 +49,7 @@ The operations should look familiar to anyone who has used the Scala Collections however they operate on streams and not collections of data (which is a very important distinction, as some operations only make sense in streaming and vice versa): -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-filter-map +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-filter-map Finally in order to :ref:`materialize ` and run the stream computation we need to attach the Flow to a :class:`Sink` that will get the Flow running. The simplest way to do this is to call @@ -57,18 +57,18 @@ the Flow to a :class:`Sink` that will get the Flow running. The simplest way to the :class:`Sink` `companion object `_. For now let's simply print each author: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-foreachsink-println +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-foreachsink-println or by using the shorthand version (which are defined only for the most popular Sinks such as ``Sink.fold`` and ``Sink.foreach``): -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-foreach-println +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#authors-foreach-println Materializing and running a stream always requires a :class:`Materializer` to be in implicit scope (or passed in explicitly, like this: ``.run(materializer)``). The complete snippet looks like this: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#first-sample +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#first-sample Flattening sequences in streams ------------------------------- @@ -77,7 +77,7 @@ we might want to map from one element to a number of elements and receive a "fla works on Scala Collections. In order to get a flattened stream of hashtags from our stream of tweets we can use the ``mapConcat`` combinator: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#hashtags-mapConcat +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#hashtags-mapConcat .. note:: The name ``flatMap`` was consciously avoided due to its proximity with for-comprehensions and monadic composition. @@ -104,7 +104,7 @@ at the expense of not reading as familiarly as collection transformations. Graphs are constructed using :class:`GraphDSL` like this: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#flow-graph-broadcast +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#flow-graph-broadcast As you can see, inside the :class:`GraphDSL` we use an implicit graph builder ``b`` to mutably construct the graph using the ``~>`` "edge operator" (also read as "connect" or "via" or "to"). The operator is provided implicitly @@ -136,7 +136,7 @@ in either ``OutOfMemoryError`` s or other severe degradations of service respons and must be handled explicitly. For example, if we are only interested in the "*most recent tweets, with a buffer of 10 elements*" this can be expressed using the ``buffer`` element: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-slow-consumption-dropHead +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-slow-consumption-dropHead The ``buffer`` element takes an explicit and required ``OverflowStrategy``, which defines how the buffer should react when it receives another element while it is full. Strategies provided include dropping the oldest element (``dropHead``), @@ -155,7 +155,7 @@ but in general it is possible to deal with finite streams and come up with a nic First, let's write such an element counter using ``Sink.fold`` and see how the types look like: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-fold-count +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-fold-count First we prepare a reusable ``Flow`` that will change each incoming tweet into an integer of value ``1``. We'll use this in order to combine those with a ``Sink.fold`` that will sum all ``Int`` elements of the stream and make its result available as @@ -181,13 +181,13 @@ and materialized multiple times, because it is just the "blueprint" of the strea for example one that consumes a live stream of tweets within a minute, the materialized values for those two materializations will be different, as illustrated by this example: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-runnable-flow-materialized-twice +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-runnable-flow-materialized-twice Many elements in Akka Streams provide materialized values which can be used for obtaining either results of computation or steering these elements which will be discussed in detail in :ref:`stream-materialization-scala`. Summing up this section, now we know what happens behind the scenes when we run this one-liner, which is equivalent to the multi line version above: -.. includecode:: code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-fold-count-oneline +.. includecode:: ../code/docs/stream/TwitterStreamQuickstartDocSpec.scala#tweets-fold-count-oneline .. note:: ``runWith()`` is a convenience method that automatically ignores the materialized value of any other stages except diff --git a/akka-docs-dev/rst/scala/stream-rate.rst b/akka-docs/rst/scala/stream/stream-rate.rst similarity index 87% rename from akka-docs-dev/rst/scala/stream-rate.rst rename to akka-docs/rst/scala/stream/stream-rate.rst index 3e43493afa..78f342ac08 100644 --- a/akka-docs-dev/rst/scala/stream-rate.rst +++ b/akka-docs/rst/scala/stream/stream-rate.rst @@ -8,7 +8,7 @@ Akka Streams processing stages are asynchronous and pipelined by default which m an element to its downstream consumer is able to immediately process the next message. To demonstrate what we mean by this, let's take a look at the following example: -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#pipelining +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#pipelining Running the above example, one of the possible outputs looks like this: @@ -64,16 +64,16 @@ to a level suitable for the throughput requirements of the application. Default Alternatively they can be set by passing a :class:`ActorMaterializerSettings` to the materializer: -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#materializer-buffer +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#materializer-buffer If the buffer size needs to be set for segments of a :class:`Flow` only, it is possible by defining a separate :class:`Flow` with these attributes: -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#section-buffer +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#section-buffer Here is an example of a code that demonstrate some of the issues caused by internal buffers: -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#buffering-abstraction-leak +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#buffering-abstraction-leak Running the above example one would expect the number *3* to be printed in every 3 seconds (the ``cUndefinedSourceonflate`` step here is configured so that it counts the number of elements received before the downstream ``ZipWith`` consumes them). What @@ -97,7 +97,7 @@ pipeline of an application. The example below will ensure that 1000 jobs (but not more) are dequeued from an external (imaginary) system and stored locally in memory - relieving the external system: -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-backpressure +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-backpressure The next example will also queue up 1000 jobs locally, but if there are more jobs waiting in the imaginary external systems, it makes space for the new element by @@ -105,12 +105,12 @@ dropping one element from the *tail* of the buffer. Dropping from the tail is a it must be noted that this will drop the *youngest* waiting job. If some "fairness" is desired in the sense that we want to be nice to jobs that has been waiting for long, then this option can be useful. -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-droptail +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-droptail Instead of dropping the youngest element from the tail of the buffer a new element can be dropped without enqueueing it to the buffer at all. -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-dropnew +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-dropnew Here is another example with a queue of 1000 jobs, but it makes space for the new element by dropping one element from the *head* of the buffer. This is the *oldest* @@ -119,13 +119,13 @@ resent if not processed in a certain period. The oldest element will be retransmitted soon, (in fact a retransmitted duplicate might be already in the queue!) so it makes sense to drop it first. -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-drophead +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-drophead Compared to the dropping strategies above, dropBuffer drops all the 1000 jobs it has enqueued once the buffer gets full. This aggressive strategy is useful when dropping jobs is preferred to delaying jobs. -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-dropbuffer +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-dropbuffer If our imaginary external job provider is a client using our API, we might want to enforce that the client cannot have more than 1000 queued jobs @@ -133,7 +133,7 @@ otherwise we consider it flooding and terminate the connection. This is easily achievable by the error strategy which simply fails the stream once the buffer gets full. -.. includecode:: code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-fail +.. includecode:: ../code/docs/stream/StreamBuffersRateSpec.scala#explicit-buffers-fail Rate transformation =================== @@ -145,13 +145,13 @@ When a fast producer can not be informed to slow down by backpressure or some ot Below is an example snippet that summarizes fast stream of elements to a standart deviation, mean and count of elements that have arrived while the stats have been calculated. -.. includecode:: code/docs/stream/RateTransformationDocSpec.scala#conflate-summarize +.. includecode:: ../code/docs/stream/RateTransformationDocSpec.scala#conflate-summarize This example demonstrates that such flow's rate is decoupled. The element rate at the start of the flow can be much higher that the element rate at the end of the flow. Another possible use of ``conflate`` is to not consider all elements for summary when producer starts getting too fast. Example below demonstrates how ``conflate`` can be used to implement random drop of elements when consumer is not able to keep up with the producer. -.. includecode:: code/docs/stream/RateTransformationDocSpec.scala#conflate-sample +.. includecode:: ../code/docs/stream/RateTransformationDocSpec.scala#conflate-sample Understanding expand -------------------- @@ -160,10 +160,10 @@ Expand helps to deal with slow producers which are unable to keep up with the de As a simple use of ``expand`` here is a flow that sends the same element to consumer when producer does not send any new elements. -.. includecode:: code/docs/stream/RateTransformationDocSpec.scala#expand-last +.. includecode:: ../code/docs/stream/RateTransformationDocSpec.scala#expand-last Expand also allows to keep some state between demand requests from the downstream. Leveraging this, here is a flow that tracks and reports a drift between fast consumer and slow producer. -.. includecode:: code/docs/stream/RateTransformationDocSpec.scala#expand-drift +.. includecode:: ../code/docs/stream/RateTransformationDocSpec.scala#expand-drift Note that all of the elements coming from upstream will go through ``expand`` at least once. This means that the output of this flow is going to report a drift of zero if producer is fast enough, or a larger drift otherwise. diff --git a/akka-docs-dev/rst/scala/stream-testkit.rst b/akka-docs/rst/scala/stream/stream-testkit.rst similarity index 83% rename from akka-docs-dev/rst/scala/stream-testkit.rst rename to akka-docs/rst/scala/stream/stream-testkit.rst index 8b5811b77a..377315e26c 100644 --- a/akka-docs-dev/rst/scala/stream-testkit.rst +++ b/akka-docs/rst/scala/stream/stream-testkit.rst @@ -25,20 +25,20 @@ elements from a predefined collection, running a constructed test flow and asserting on the results that sink produced. Here is an example of a test for a sink: -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#strict-collection +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#strict-collection The same strategy can be applied for sources as well. In the next example we have a source that produces an infinite stream of elements. Such source can be tested by asserting that first arbitrary number of elements hold some condition. Here the ``grouped`` combinator and ``Sink.head`` are very useful. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#grouped-infinite +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#grouped-infinite When testing a flow we need to attach a source and a sink. As both stream ends are under our control, we can choose sources that tests various edge cases of the flow and sinks that ease assertions. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#folded-stream +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#folded-stream TestKit ======= @@ -51,7 +51,7 @@ One of the more straightforward tests would be to materialize stream to a :class:`Future` and then use ``pipe`` pattern to pipe the result of that future to the probe. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#pipeto-testprobe +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#pipeto-testprobe Instead of materializing to a future, we can use a :class:`Sink.actorRef` that sends all incoming elements to the given :class:`ActorRef`. Now we can use @@ -59,13 +59,13 @@ assertion methods on :class:`TestProbe` and expect elements one by one as they arrive. We can also assert stream completion by expecting for ``onCompleteMessage`` which was given to :class:`Sink.actorRef`. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#sink-actorref +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#sink-actorref Similarly to :class:`Sink.actorRef` that provides control over received elements, we can use :class:`Source.actorRef` and have full control over elements to be sent. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#source-actorref +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#source-actorref Streams TestKit =============== @@ -83,20 +83,20 @@ provide sources and sinks that materialize to probes that allow fluent API. A sink returned by ``TestSink.probe`` allows manual control over demand and assertions over elements coming downstream. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#test-sink-probe +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#test-sink-probe A source returned by ``TestSource.probe`` can be used for asserting demand or controlling when stream is completed or ended with an error. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#test-source-probe +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#test-source-probe You can also inject exceptions and test sink behaviour on error conditions. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#injecting-failure +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#injecting-failure Test source and sink can be used together in combination when testing flows. -.. includecode:: code/docs/stream/StreamTestKitDocSpec.scala#test-source-and-sink +.. includecode:: ../code/docs/stream/StreamTestKitDocSpec.scala#test-source-and-sink Fuzzing Mode diff --git a/akka-docs/src/test/resources/application.conf b/akka-docs/src/test/resources/application.conf new file mode 100644 index 0000000000..9e04966ad7 --- /dev/null +++ b/akka-docs/src/test/resources/application.conf @@ -0,0 +1,2 @@ +//akka.loggers = ["akka.testkit.TestEventListener"] +akka.loggers = [] diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index f24230db3b..e82c78d89a 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -403,10 +403,16 @@ object AkkaBuild extends Build { lazy val docs = Project( id = "akka-docs", base = file("akka-docs"), - dependencies = Seq(actor, testkit % "test->test", + dependencies = Seq( + actor, + testkit % "compile;test->test", remote % "compile;test->test", cluster, clusterMetrics, slf4j, agent, camel, osgi, persistence % "compile;provided->provided;test->test", persistenceTck, persistenceQuery, - typed % "compile;test->test", distributedData) + typed % "compile;test->test", distributedData, + stream, streamTestkit % "compile;test->test", + http, httpSprayJson, httpJackson, httpXml, + httpTests % "compile;test->test", httpTestkit % "compile;test->test" + ) ) lazy val docsDev = Project( diff --git a/project/Doc.scala b/project/Doc.scala index 96b43574aa..08c86b7cab 100644 --- a/project/Doc.scala +++ b/project/Doc.scala @@ -100,7 +100,7 @@ object UnidocRoot extends AutoPlugin { override def trigger = noTrigger val akkaSettings = UnidocRoot.CliOptions.genjavadocEnabled.ifTrue(Seq( - javacOptions in (JavaUnidoc, unidoc) ++= Seq("-Xdoclint:none"), // TODO likely still needed + javacOptions in (JavaUnidoc, unidoc) ++= Seq("-Xdoclint:none"), // genjavadoc needs to generate synthetic methods since the java code uses them scalacOptions += "-P:genjavadoc:suppressSynthetic=false", // FIXME: see #18056