├── .gitignore ├── ClojureExamples ├── project.clj ├── src │ ├── java │ │ └── com │ │ │ └── mblinn │ │ │ └── oo │ │ │ └── tinyweb │ │ │ ├── Controller.java │ │ │ ├── ControllerException.java │ │ │ ├── Filter.java │ │ │ ├── HttpRequest.java │ │ │ ├── HttpResponse.java │ │ │ ├── RenderingException.java │ │ │ ├── RenderingStrategy.java │ │ │ ├── StrategyView.java │ │ │ ├── TemplateController.java │ │ │ ├── TinyWeb.java │ │ │ ├── View.java │ │ │ └── example │ │ │ ├── ExampleHarness.java │ │ │ ├── GreetingController.java │ │ │ ├── GreetingRenderingStrategy.java │ │ │ └── LoggingFilter.java │ └── mbfpp │ │ ├── functional │ │ ├── ccf │ │ │ └── ccf_examples.clj │ │ ├── coo │ │ │ └── examples.clj │ │ ├── di │ │ │ └── examples.clj │ │ ├── dsl │ │ │ └── examples.clj │ │ ├── fb │ │ │ ├── composition_examples.clj │ │ │ ├── discount_builder.clj │ │ │ ├── partial_examples.clj │ │ │ └── selector.clj │ │ ├── fm │ │ │ └── examples.clj │ │ ├── ls │ │ │ └── examples.clj │ │ ├── memoization │ │ │ └── examples.clj │ │ ├── mfr │ │ │ └── discount.clj │ │ ├── mr │ │ │ └── phases.clj │ │ └── tr │ │ │ └── names.clj │ │ ├── oo │ │ ├── command │ │ │ └── cash_register.clj │ │ ├── decorator │ │ │ └── examples.clj │ │ ├── iterator │ │ │ ├── higher_order_functions.clj │ │ │ └── lambda_bar_and_grille.clj │ │ ├── javabean │ │ │ ├── catsanddogslivingtogether.clj │ │ │ ├── person.clj │ │ │ └── sidebar.clj │ │ ├── nullobject │ │ │ └── examples.clj │ │ ├── strategy │ │ │ └── people_example.clj │ │ ├── tinyweb │ │ │ ├── RenderingException.java │ │ │ ├── core.clj │ │ │ ├── example.clj │ │ │ ├── intro.clj │ │ │ ├── stepone.clj │ │ │ └── steptwo.clj │ │ ├── tm │ │ │ └── grade_reporter.clj │ │ └── visitor │ │ │ └── examples.clj │ │ └── rso │ │ ├── closure_comparison.clj │ │ ├── closure_example.clj │ │ ├── logging.clj │ │ ├── person.clj │ │ └── person_expanded.clj └── test │ └── mbfpp │ └── test │ ├── functional │ ├── fb │ │ ├── composition_examples.clj │ │ ├── discount_builder.clj │ │ ├── partial_examples.clj │ │ └── selector.clj │ ├── mfr │ │ └── discount.clj │ ├── mr │ │ └── phases.clj │ └── tr │ │ └── names.clj │ └── oo │ ├── command │ └── cash_register.clj │ ├── iterator │ ├── higher_order_functions.clj │ └── lambda_bar_and_grille.clj │ ├── javabean │ └── catsanddogslivingtogether.clj │ └── tinyweb │ └── core.clj ├── JavaExamples ├── build.sbt ├── project │ └── plugins.sbt └── src │ ├── main │ └── java │ │ └── com │ │ └── mblinn │ │ ├── ex │ │ ├── recursion │ │ │ └── RecursionExample.java │ │ └── repeating │ │ │ └── VowelFilter.java │ │ ├── functional │ │ └── tailrecursion │ │ │ └── Sum.java │ │ ├── mbfpp │ │ ├── functional │ │ │ └── coo │ │ │ │ └── Examples.java │ │ ├── intro │ │ │ └── FilterOdds.java │ │ └── oo │ │ │ ├── command │ │ │ ├── CashRegister.java │ │ │ ├── Command.java │ │ │ ├── Purchase.java │ │ │ ├── PurchaseInvoker.java │ │ │ └── RegisterClient.java │ │ │ ├── di │ │ │ ├── FavoritesService.java │ │ │ ├── MovieDao.java │ │ │ ├── MovieService.java │ │ │ └── ex1 │ │ │ │ ├── DecoratedMovie.java │ │ │ │ ├── FavoriteVideosService.java │ │ │ │ ├── FavoritesService.java │ │ │ │ ├── Movie.java │ │ │ │ ├── MovieDao.java │ │ │ │ ├── MovieService.java │ │ │ │ └── VideoService.java │ │ │ ├── fi │ │ │ ├── ComplicatedNameComparator.java │ │ │ ├── ComposedComparator.java │ │ │ ├── Harness.java │ │ │ ├── Person.java │ │ │ ├── PersonComplicatedSort.java │ │ │ ├── PersonExpanded.java │ │ │ ├── PersonFirstNameSort.java │ │ │ └── PersonNaturalSort.java │ │ │ └── tm │ │ │ ├── FullGradeReporter.java │ │ │ ├── GradeReporterTemplate.java │ │ │ └── PlusMinusGradeReporter.java │ │ └── oo │ │ ├── iterator │ │ ├── Address.java │ │ ├── HigherOrderFunctions.java │ │ ├── Person.java │ │ └── TheLambdaBarAndGrille.java │ │ ├── javabean │ │ ├── ImmutablePerson.java │ │ ├── Person.java │ │ └── PersonHarness.java │ │ ├── nullobject │ │ ├── NullPerson.java │ │ ├── Person.java │ │ ├── PersonExample.java │ │ └── RealPerson.java │ │ ├── strategy │ │ ├── FirstNameValidator.java │ │ ├── FullNameValidator.java │ │ ├── Person.java │ │ ├── PersonCollector.java │ │ └── PersonValidator.java │ │ └── tinyweb │ │ ├── Controller.java │ │ ├── ControllerException.java │ │ ├── Filter.java │ │ ├── HttpRequest.java │ │ ├── HttpResponse.java │ │ ├── RenderingException.java │ │ ├── RenderingStrategy.java │ │ ├── StrategyView.java │ │ ├── TemplateController.java │ │ ├── TinyWeb.java │ │ ├── View.java │ │ └── example │ │ ├── ExampleHarness.java │ │ ├── GreetingController.java │ │ ├── GreetingRenderingStrategy.java │ │ └── LoggingFilter.java │ └── test │ └── java │ └── com │ └── mblinn │ ├── mbfpp │ └── oo │ │ ├── fi │ │ └── PersonExpandedTest.java │ │ └── tinyweb │ │ ├── CommandViewTest.java │ │ ├── HttpRequestResponseTest.java │ │ ├── ITestTinyweb.java │ │ ├── TemplateControllerTest.java │ │ └── stubs │ │ ├── AddDummyHeaderFilter.java │ │ ├── DummyController.java │ │ ├── DummyView.java │ │ ├── DummyViewRenderer.java │ │ ├── ExceptionalController.java │ │ ├── ExceptionalView.java │ │ └── ExceptionalViewRenderer.java │ └── oo │ ├── command │ ├── CashRegisterTests.java │ ├── PurchaseInvokerTests.java │ └── RecordingStubCommand.java │ ├── iterator │ └── HigherOrderFunctionsTests.java │ └── strategy │ ├── DummyValidator.java │ ├── FirstNameValidatorTest.java │ ├── FullNameValidatorTest.java │ └── PersonCollectorTest.java ├── README.md ├── ScalaExamples ├── build.sbt ├── project │ └── sbt-idea-shim.sbt └── src │ ├── main │ └── scala │ │ └── com │ │ └── mblinn │ │ └── mbfpp │ │ ├── functional │ │ ├── ccf │ │ │ └── Choose.scala │ │ ├── coo │ │ │ └── Examples.scala │ │ ├── dsl │ │ │ └── Example.scala │ │ ├── fb │ │ │ ├── CompositionExamples.scala │ │ │ ├── DiscountBuilder.scala │ │ │ ├── PartialExamples.scala │ │ │ └── Selector.scala │ │ ├── fm │ │ │ └── FocusedMutation.scala │ │ ├── ls │ │ │ └── LazySequence.scala │ │ ├── memoization │ │ │ └── Examples.scala │ │ ├── mfr │ │ │ └── Discount.scala │ │ ├── mr │ │ │ ├── EvenOdd.scala │ │ │ └── Phases.scala │ │ └── tr │ │ │ └── Names.scala │ │ └── oo │ │ ├── command │ │ └── register │ │ │ └── Register.scala │ │ ├── decorator │ │ └── Examples.scala │ │ ├── di │ │ └── ex1 │ │ │ └── Services.scala │ │ ├── fi │ │ ├── PersonExample.scala │ │ ├── PersonExpanded.scala │ │ └── personexpanded │ │ │ └── ClosureExample.scala │ │ ├── iterator │ │ ├── HigherOrderFunctions.scala │ │ └── TheLambdaBarAndGrille.scala │ │ ├── javabean │ │ └── Person.scala │ │ ├── nullobject │ │ └── Examples.scala │ │ ├── strategy │ │ └── PeopleExample.scala │ │ ├── tinyweb │ │ ├── example │ │ │ └── Example.scala │ │ ├── stepfour │ │ │ ├── Controller.scala │ │ │ ├── HttpData.scala │ │ │ ├── Tinyweb.scala │ │ │ └── View.scala │ │ ├── stepone │ │ │ └── View.scala │ │ ├── stepthree │ │ │ ├── Controller.scala │ │ │ ├── HttpData.scala │ │ │ └── View.scala │ │ └── steptwo │ │ │ ├── Controller.scala │ │ │ └── View.scala │ │ ├── tm │ │ └── GradeReporter.scala │ │ └── visitor │ │ ├── Examples.scala │ │ └── Shapes.scala │ └── test │ └── scala │ └── com │ └── mblinn │ └── mbfpp │ ├── functional │ ├── ccf │ │ └── ChooseSpec.scala │ ├── fb │ │ ├── DiscountBuilder.scala │ │ └── Selector.scala │ ├── mfr │ │ └── DiscountSpec.scala │ ├── mr │ │ ├── EvenOddSpec.scala │ │ └── PhasesSpec.scala │ ├── strategy │ │ └── PeopleExampleSpec.scala │ └── tr │ │ └── NamesSpec.scala │ └── oo │ ├── fi │ └── PersonExampleSpec.scala │ └── iterator │ ├── HigherOrderFunctions.scala │ └── LambdaBarAndGrille.scala ├── build.sbt └── project └── sbt-idea-shim.sbt /.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | pom.xml.asc 3 | *jar 4 | /lib/ 5 | /classes/ 6 | /target/ 7 | /checkouts/ 8 | .lein-deps-sum 9 | .lein-repl-history 10 | .lein-plugins/ 11 | .lein-failures 12 | *.class 13 | *.log 14 | 15 | # sbt specific 16 | .cache/ 17 | .history/ 18 | .lib/ 19 | dist/* 20 | target/ 21 | lib_managed/ 22 | src_managed/ 23 | project/boot/ 24 | project/plugins/project/ 25 | 26 | # Intellij 27 | .idea/ 28 | *.iml 29 | *.iws 30 | 31 | # Mac 32 | .DS_Store 33 | -------------------------------------------------------------------------------- /ClojureExamples/project.clj: -------------------------------------------------------------------------------- 1 | (defproject ClojureExamples "0.1.0-SNAPSHOT" 2 | :description "Clojure examples for Patterns and Functional Programming" 3 | :java-source-paths ["src/java"] 4 | :dependencies [[org.clojure/clojure "1.3.0"]] 5 | :profiles { 6 | :dev {:dependencies [[midje "1.4.0"]] 7 | :plugins [[lein-midje "2.0.0-SNAPSHOT"] 8 | [no-man-is-an-island/lein-eclipse "2.0.0"]]}}) 9 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/Controller.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public interface Controller { 12 | public HttpResponse handleRequest(HttpRequest httpRequest); 13 | } 14 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/ControllerException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class ControllerException extends RuntimeException { 12 | private Integer statusCode; 13 | 14 | public ControllerException(Integer statusCode) { 15 | this.statusCode = statusCode; 16 | } 17 | 18 | public Integer getStatusCode() { 19 | return statusCode; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/Filter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public interface Filter { 12 | public HttpRequest doFilter(HttpRequest request); 13 | } 14 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/HttpRequest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.Collections; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class HttpRequest { 16 | private Map headers; 17 | private String body; 18 | private String path; 19 | 20 | public Map getHeaders() { 21 | return headers; 22 | } 23 | 24 | public String getBody() { 25 | return body; 26 | } 27 | 28 | public String getPath() { 29 | return path; 30 | } 31 | 32 | private HttpRequest(Builder builder) { 33 | this.headers = Collections.unmodifiableMap(builder.headers); 34 | this.body = builder.body; 35 | this.path = builder.path; 36 | } 37 | 38 | public static class Builder { 39 | private Map headers; 40 | private String body; 41 | private String path; 42 | 43 | private Builder() { 44 | headers = new HashMap(); 45 | } 46 | 47 | public Builder addHeader(String name, String value) { 48 | headers.put(name, value); 49 | return this; 50 | } 51 | 52 | public Builder body(String body) { 53 | this.body = body; 54 | return this; 55 | } 56 | 57 | public Builder path(String path) { 58 | this.path = path; 59 | return this; 60 | } 61 | 62 | public HttpRequest build() { 63 | return new HttpRequest(this); 64 | } 65 | 66 | public static Builder newBuilder() { 67 | return new Builder(); 68 | } 69 | 70 | public static Builder builderFrom(HttpRequest request) { 71 | Builder builder = new Builder(); 72 | builder.path(request.getPath()); 73 | builder.body(request.getBody()); 74 | 75 | Map headers = request.getHeaders(); 76 | for (String headerName : headers.keySet()) 77 | builder.addHeader(headerName, 78 | headers.get(headerName)); 79 | 80 | return builder; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/HttpResponse.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class HttpResponse { 12 | private final String body; 13 | private final Integer responseCode; 14 | 15 | public String getBody() { 16 | return body; 17 | } 18 | 19 | public Integer getResponseCode() { 20 | return responseCode; 21 | } 22 | 23 | private HttpResponse(Builder builder) { 24 | body = builder.body; 25 | responseCode = builder.responseCode; 26 | } 27 | 28 | public static class Builder { 29 | private String body; 30 | private Integer responseCode; 31 | 32 | public Builder body(String body) { 33 | this.body = body; 34 | return this; 35 | } 36 | 37 | public Builder responseCode(Integer responseCode) { 38 | this.responseCode = responseCode; 39 | return this; 40 | } 41 | 42 | public HttpResponse build() { 43 | return new HttpResponse(this); 44 | } 45 | 46 | public static Builder newBuilder() { 47 | return new Builder(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/RenderingException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class RenderingException extends RuntimeException { 12 | 13 | public RenderingException(Exception e) { 14 | super(e); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/RenderingStrategy.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public interface RenderingStrategy { 15 | 16 | public String renderView(Map> model); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/StrategyView.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class StrategyView implements View { 15 | 16 | private RenderingStrategy viewRenderer; 17 | 18 | public StrategyView(RenderingStrategy viewRenderer) { 19 | this.viewRenderer = viewRenderer; 20 | } 21 | 22 | @Override 23 | public String render(Map> model) { 24 | try { 25 | return viewRenderer.renderView(model); 26 | } catch (Exception e) { 27 | throw new RenderingException(e); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/TemplateController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public abstract class TemplateController implements Controller { 15 | private View view; 16 | public TemplateController(View view) { 17 | this.view = view; 18 | } 19 | 20 | public HttpResponse handleRequest(HttpRequest request) { 21 | Integer responseCode = 200; 22 | String responseBody = ""; 23 | 24 | try { 25 | Map> model = doRequest(request); 26 | responseBody = view.render(model); 27 | } catch (ControllerException e) { 28 | responseCode = e.getStatusCode(); 29 | } catch (RenderingException e) { 30 | responseCode = 500; 31 | responseBody = "Exception while rendering."; 32 | } catch (Exception e) { 33 | responseCode = 500; 34 | } 35 | 36 | return HttpResponse.Builder.newBuilder().body(responseBody) 37 | .responseCode(responseCode).build(); 38 | } 39 | protected abstract Map> doRequest(HttpRequest request); 40 | } 41 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/TinyWeb.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class TinyWeb { 15 | private Map controllers; 16 | private List filters; 17 | 18 | public TinyWeb(Map controllers, List filters) { 19 | this.controllers = controllers; 20 | this.filters = filters; 21 | } 22 | 23 | public HttpResponse handleRequest(HttpRequest httpRequest) { 24 | 25 | HttpRequest currentRequest = httpRequest; 26 | for (Filter filter : filters) { 27 | currentRequest = filter.doFilter(currentRequest); 28 | } 29 | 30 | Controller controller = controllers.get(currentRequest.getPath()); 31 | 32 | if (null == controller) 33 | return null; 34 | 35 | return controller.handleRequest(currentRequest); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/View.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public interface View { 15 | public String render(Map> model); 16 | } 17 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/example/ExampleHarness.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | import com.mblinn.oo.tinyweb.StrategyView; 18 | import com.mblinn.oo.tinyweb.Controller; 19 | import com.mblinn.oo.tinyweb.Filter; 20 | import com.mblinn.oo.tinyweb.HttpRequest; 21 | import com.mblinn.oo.tinyweb.HttpResponse; 22 | import com.mblinn.oo.tinyweb.TinyWeb; 23 | 24 | public class ExampleHarness { 25 | 26 | public static void main(String[] args){ 27 | 28 | TinyWeb tinyWeb = new TinyWeb(makeRoutes(), makeFilters()); 29 | 30 | HttpRequest testRequest = HttpRequest.Builder.newBuilder() 31 | .path("greeting/") 32 | .body("Mike,Joe,John,Steve") 33 | .addHeader("X-Example", "exampleHeader") 34 | .build(); 35 | 36 | HttpResponse testResponse = tinyWeb.handleRequest(testRequest); 37 | 38 | System.out.println("responseCode: " + testResponse.getResponseCode()); 39 | System.out.println("responseBody: "); 40 | System.out.println(testResponse.getBody()); 41 | } 42 | 43 | private static Map makeRoutes(){ 44 | GreetingRenderingStrategy viewRenderer = new GreetingRenderingStrategy(); 45 | StrategyView greetingView = new StrategyView(viewRenderer); 46 | GreetingController greetingController = new GreetingController(greetingView); 47 | 48 | Map controllers = new HashMap(); 49 | controllers.put("greeting/", greetingController); 50 | return Collections.unmodifiableMap(controllers); 51 | } 52 | 53 | private static List makeFilters(){ 54 | List filters = new ArrayList(); 55 | filters.add(new LoggingFilter()); 56 | return filters; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/example/GreetingController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Random; 15 | 16 | import com.mblinn.oo.tinyweb.HttpRequest; 17 | import com.mblinn.oo.tinyweb.TemplateController; 18 | import com.mblinn.oo.tinyweb.View; 19 | 20 | public class GreetingController extends TemplateController { 21 | private Random random; 22 | public GreetingController(View view) { 23 | super(view); 24 | random = new Random(); 25 | } 26 | 27 | @Override 28 | public Map> doRequest(HttpRequest httpRequest) { 29 | Map> helloModel = 30 | new HashMap>(); 31 | helloModel.put("greetings", 32 | generateGreetings(httpRequest.getBody())); 33 | return helloModel; 34 | } 35 | 36 | private List generateGreetings(String namesCommaSeperated) { 37 | String[] names = namesCommaSeperated.split(","); 38 | List greetings = new ArrayList(); 39 | for (String name : names) { 40 | greetings.add(makeGreeting(name)); 41 | } 42 | return greetings; 43 | } 44 | 45 | private String makeGreeting(String name) { 46 | String[] greetings = 47 | { "Hello", "Greetings", "Salutations", "Hola" }; 48 | String greetingPrefix = greetings[random.nextInt(4)]; 49 | return String.format("%s, %s", greetingPrefix, name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/example/GreetingRenderingStrategy.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.RenderingStrategy; 15 | 16 | public class GreetingRenderingStrategy implements RenderingStrategy { 17 | 18 | @Override 19 | public String renderView(Map> model) { 20 | List greetings = model.get("greetings"); 21 | StringBuffer responseBody = new StringBuffer(); 22 | responseBody.append("

Friendly Greetings:

\n"); 23 | for (String greeting : greetings) { 24 | responseBody.append( 25 | String.format("

%s

\n", greeting)); 26 | 27 | } 28 | return responseBody.toString(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /ClojureExamples/src/java/com/mblinn/oo/tinyweb/example/LoggingFilter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import com.mblinn.oo.tinyweb.Filter; 12 | import com.mblinn.oo.tinyweb.HttpRequest; 13 | 14 | public class LoggingFilter implements Filter { 15 | 16 | @Override 17 | public HttpRequest doFilter(HttpRequest request) { 18 | System.out.println("In Logging Filter - request for path: " 19 | + request.getPath()); 20 | return request; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/ccf/ccf_examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.ccf.ccf-examples) 2 | 3 | (defmacro make-logger [name form] 4 | `(defn ~name [] 5 | (println (str "Calling " ~name)) 6 | ~form)) 7 | 8 | (defn choose [num first second third] 9 | (cond 10 | (= 1 num) (first) 11 | (= 2 num) (second) 12 | (= 3 num) (third))) 13 | 14 | (defmacro simpler-choose [num first second third] 15 | `(cond 16 | (= 1 ~num) ~first 17 | (= 2 ~num) ~second 18 | (= 3 ~num) ~third)) 19 | 20 | (defn time-run [to-time] 21 | (let [start (System/currentTimeMillis)] 22 | (to-time) 23 | (- (System/currentTimeMillis) start))) 24 | 25 | (defmacro avg-time [times to-time] 26 | `(let [total-time# 27 | (apply + (for [_# (range ~times)] (time-run (fn [] ~to-time))))] 28 | (float (/ total-time# ~times)))) 29 | 30 | (defn avg-time-fn [times to-time] 31 | (let [total-time 32 | (apply + (for [_ (range times)] (time-run to-time)))] 33 | (float (/ total-time times)))) 34 | 35 | (let 36 | [total-time 37 | (apply + (for [_ (range 5)] (time-run (fn [] (Thread/sleep 100)))))] 38 | (float (/ total-time 5))) 39 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/coo/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.coo.examples 2 | (:require [clojure.string :as string])) 3 | 4 | (def my-name "michael bevilacqua linn") 5 | (defn get-intitals [] 6 | (apply str (map first (string/split my-name #" ")))) 7 | 8 | (def v1 9 | {:title "Pianocat Plays Carnegie Hall" 10 | :type :cat 11 | :length 300}) 12 | 13 | (def v2 14 | {:title "Paint Drying" 15 | :type :home-improvement 16 | :length 600}) 17 | 18 | (def v3 19 | {:title "Fuzzy McMittens Live At The Apollo" 20 | :type :cat 21 | :length 200}) 22 | 23 | (def videos [v1 v2 v3]) 24 | 25 | (defn cat-time [videos] 26 | (apply + 27 | (map :length 28 | (filter (fn [video] (= :cat (:type video))) videos)))) 29 | 30 | ; (-> 4 (- 2) (- 2)) 31 | ; (->> 4 (- 2) (- 2)) 32 | 33 | (-> 4 (- 2) (- 2)) 34 | 35 | (->> 4 (- 2) (- 2)) 36 | 37 | (defn more-cat-time [videos] 38 | (->> videos 39 | (filter (fn [video] (= :cat (:type video)))) 40 | (map :length) 41 | (apply +))) 42 | 43 | (def v1 [42]) 44 | (def v2 [8]) 45 | 46 | (def v3 []) 47 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/di/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.di.examples) 2 | 3 | (defn get-movie [movie-id] 4 | {:id "42" :title "A Movie"}) 5 | 6 | (defn get-favorite-videos [user-id] 7 | [{:id "1"}]) 8 | 9 | (defn get-favorite-decorated-videos [user-id get-movie get-favorite-videos] 10 | (for [video (get-favorite-videos user-id)] 11 | {:movie (get-movie (:id video)) 12 | :video video})) 13 | 14 | (defn get-test-movie [movie-id] 15 | {:id "43" :title "A Test Movie"}) 16 | 17 | (defn get-test-favorite-videos [user-id] 18 | [{:id "2"}]) 19 | 20 | (defn get-favorite-decorated-videos-2 [user-id] 21 | (for [video (get-favorite-videos user-id)] 22 | {:movie (get-movie (:id video)) 23 | :video video})) 24 | 25 | (with-redefs 26 | [get-favorite-videos get-test-favorite-videos 27 | get-movie get-test-movie] 28 | (doall (get-favorite-decorated-videos-2 "2"))) 29 | 30 | (defn dep [] "dep") 31 | 32 | (defn test-dep [] "test-dep") 33 | 34 | (defn outer-1 [] 35 | (conj (for [foo (range 0 1)] (dep)) (dep))) 36 | 37 | (defn outer-2 [] 38 | (for [foo (range 0 1)] (dep))) -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/dsl/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.dsl.examples 2 | (:require [clojure.string :as str] 3 | [clojure.java.shell :as shell])) 4 | 5 | (defn- print-output [output] 6 | (println (str "Exit Code: " (:exit output))) 7 | (if-not (str/blank? (:out output)) (println (:out output))) 8 | (if-not (str/blank? (:err output)) (println (:err output))) 9 | output) 10 | 11 | (defn command [command-str] 12 | (let [command-parts (str/split command-str #"\s+")] 13 | (fn [] 14 | (print-output (apply shell/sh command-parts))))) 15 | 16 | (defn command [command-str] 17 | (let [command-parts (str/split command-str #"\s+")] 18 | (fn 19 | ([] (print-output (apply shell/sh command-parts))) 20 | ([{old-out :out}] 21 | (print-output (apply shell/sh (concat command-parts [:in old-out]))))))) 22 | 23 | (defn pipe [commands] 24 | (apply comp (reverse commands))) 25 | 26 | (defmacro def-command [name command-str] 27 | `(def ~name ~(command command-str))) 28 | 29 | (defmacro def-pipe [name & command-strs] 30 | (let [commands (map command command-strs) 31 | pipe (pipe commands)] 32 | `(def ~name ~pipe))) 33 | 34 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/fb/composition_examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.fb.composition-examples) 2 | 3 | (defn append-a [s] (str s "a")) 4 | (defn append-b [s] (str s "b")) 5 | (defn append-c [s] (str s "c")) 6 | 7 | (def append-cba (comp append-a append-b append-c)) 8 | 9 | (def request 10 | {:headers 11 | {"Authorization" "auth" 12 | "X-RequestFingerprint" "fingerprint"} 13 | :body "body"}) 14 | 15 | (defn check-authorization [request] 16 | (let [auth-header (get-in request [:headers "Authorization"])] 17 | (assoc 18 | request 19 | :principal 20 | (if-not (nil? auth-header) 21 | "AUser")))) 22 | 23 | (defn log-fingerprint [request] 24 | (let [fingerprint (get-in request [:headers "X-RequestFingerprint"])] 25 | (println (str "FINGERPRINT=" fingerprint)) 26 | request)) 27 | 28 | (defn compose-filters [filters] 29 | (reduce 30 | (fn [all-filters, current-filter] (comp all-filters current-filter)) 31 | filters)) 32 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/fb/discount_builder.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.fb.discount-builder) 2 | 3 | (defn discount [percentage] 4 | {:pre [(and (>= percentage 0) (<= percentage 100))]} 5 | (fn [price] (- price (* price percentage 0.01)))) 6 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/fb/partial_examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.fb.partial-examples) 2 | 3 | (defn add-two-ints [int-one int-two] (+ int-one int-two)) 4 | 5 | (def add-fourty-two (partial add-two-ints 42)) 6 | 7 | (defn tax-for-state [state amount] 8 | (cond 9 | (= :ny state) (* amount 0.0645) 10 | (= :pa state) (* amount 0.045))) 11 | 12 | (def ny-tax (partial tax-for-state :ny)) 13 | (def pa-tax (partial tax-for-state :pa)) 14 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/fb/selector.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.fb.selector) 2 | 3 | (defn selector [& path] 4 | {:pre [(not (empty? path))]} 5 | (fn [ds] (get-in ds path))) 6 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/fm/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.fm.examples) 2 | 3 | (def one-million 1000000) 4 | (def five-hundred-thousand 500000) 5 | 6 | (defmacro time-runs [fn count] 7 | `(dotimes [_# ~count] 8 | (time ~fn))) 9 | 10 | (defn test-mutable [count] 11 | (loop [i 0 s (transient [])] 12 | (if (< i count) 13 | (recur (inc i) (conj! s i)) 14 | (persistent! s)))) 15 | 16 | (defn test-immutable [count] 17 | (loop [i 0 s []] 18 | (if (< i count) 19 | (recur (inc i) (conj s i)) 20 | s))) 21 | 22 | (defn make-test-purchase [] 23 | {:store-number (rand-int 100) 24 | :customer-number (rand-int 100) 25 | :item-number (rand-int 500)}) 26 | (defn infinite-test-purchases [] 27 | (repeatedly make-test-purchase)) 28 | 29 | (defn immutable-sequence-event-processing [count] 30 | (let [test-purchases (take count (infinite-test-purchases))] 31 | (reduce 32 | (fn [map-of-purchases {:keys [store-number] :as current-purchase}] 33 | (let [purchases-for-store (get map-of-purchases store-number '())] 34 | (assoc map-of-purchases store-number 35 | (conj purchases-for-store current-purchase)))) 36 | {} 37 | test-purchases))) 38 | 39 | (defn mutable-sequence-event-processing [count] 40 | (let [test-purchases (take count (infinite-test-purchases))] 41 | (persistent! (reduce 42 | (fn [map-of-purchases {:keys [store-number] :as current-purchase}] 43 | (let [purchases-for-store (get map-of-purchases store-number '())] 44 | (assoc! map-of-purchases store-number 45 | (conj purchases-for-store current-purchase)))) 46 | (transient {}) 47 | test-purchases)))) 48 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/ls/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.ls.examples) 2 | 3 | (def integers (range Integer/MAX_VALUE)) 4 | 5 | (def randoms (repeatedly (fn [] (rand-int Integer/MAX_VALUE)))) 6 | 7 | (defn get-page [page-num] 8 | (cond 9 | (= page-num 1) "Page1" 10 | (= page-num 2) "Page2" 11 | (= page-num 3) "Page3" 12 | :default nil)) 13 | 14 | (defn paged-sequence [page-num] 15 | (let [page (get-page page-num)] 16 | (when page 17 | (cons page (lazy-seq (paged-sequence (inc page-num))))))) 18 | 19 | (defn paged-sequence-print [page-num] 20 | (let [page (get-page page-num)] 21 | (when page 22 | (println (str "Realizing " page)) 23 | (cons page (lazy-seq (paged-sequence (inc page-num))))))) 24 | 25 | (defn print-num [num] (print (str num " "))) 26 | 27 | (def print-hellos (repeatedly (fn [] (println "hello, world")))) -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/memoization/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.memoization.examples) 2 | 3 | (defn expensive-lookup [id] 4 | (Thread/sleep 1000) 5 | (println (str "Lookup for " id)) 6 | ({42 "foo" 12 "bar" 1 "baz"} id)) 7 | 8 | (def memoized-expensive-lookup 9 | (memoize expensive-lookup)) 10 | 11 | (def slow-fib 12 | (fn [n] 13 | (cond 14 | (<= n 0) 0 15 | (< n 2) 1 16 | :else (+ (slow-fib (- n 1)) (slow-fib (- n 2)))))) 17 | 18 | (def mem-fib 19 | (memoize 20 | (fn [n] 21 | (cond 22 | (<= n 0) 0 23 | (< n 2) 1 24 | :else (+ (mem-fib (- n 1)) (mem-fib (- n 2))))))) 25 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/mfr/discount.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.mfr.discount) 2 | 3 | (defn calculate-discount [prices] 4 | (reduce + 5 | (map (fn [price] (* price 0.10)) 6 | (filter (fn [price] (>= price 20.0)) prices)))) 7 | 8 | (defn calculate-discount-namedfn [prices] 9 | (letfn [(twenty-or-greater? [price] (>= price 20.0)) 10 | (ten-percent [price] (* price 0.10))] 11 | (reduce + 0.0 (map ten-percent (filter twenty-or-greater? prices))))) 12 | 13 | (def bill [20.0 4.5 50.0 15.75 30.0 3.50]) -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/mr/phases.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.mr.phases) 2 | 3 | (declare plasma vapor liquid solid) 4 | 5 | (defn plasma [[transition & rest-transitions]] 6 | #(case transition 7 | nil true 8 | :deionization (vapor rest-transitions) 9 | :false)) 10 | 11 | (defn vapor [[transition & rest-transitions]] 12 | #(case transition 13 | nil true 14 | :condensation (liquid rest-transitions) 15 | :deposition (solid rest-transitions) 16 | :ionization (plasma rest-transitions) 17 | false)) 18 | 19 | (defn liquid [[transition & rest-transitions]] 20 | #(case transition 21 | nil true 22 | :vaporization (vapor rest-transitions) 23 | :freezing (solid rest-transitions) 24 | false)) 25 | 26 | (defn solid [[transition & rest-transitions]] 27 | #(case transition 28 | nil true 29 | :melting (liquid rest-transitions) 30 | :sublimation (vapor rest-transitions) 31 | false)) 32 | 33 | (def valid-sequence [:melting :vaporization :ionization :deionization]) 34 | (def invalid-sequence [:vaporization :freezing]) -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/functional/tr/names.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.functional.tr.names) 2 | 3 | (defn make-people [first-names last-names] 4 | (loop [first-names first-names last-names last-names people []] 5 | (if (seq first-names) 6 | (recur 7 | (rest first-names) 8 | (rest last-names) 9 | (conj 10 | people 11 | {:first (first first-names) :last (first last-names)})) 12 | people))) 13 | 14 | (defn shorter-make-people [first-names last-names] 15 | (for [[first last] (partition 2 (interleave first-names last-names))] 16 | {:first first :last last})) 17 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/command/cash_register.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.command.cash-register) 2 | 3 | ; 4 | (defn make-cash-register [] 5 | (let [register (atom 0)] 6 | (set-validator! register (fn [new-total] (>= new-total 0))) 7 | register)) 8 | 9 | (defn add-cash [register to-add] 10 | (swap! register + to-add)) 11 | 12 | (defn reset [register] 13 | (swap! register (fn [oldval] 0))) 14 | ; 15 | 16 | ; 17 | (defn make-purchase [register amount] 18 | (fn [] 19 | (println (str "Purchase in amount: " amount)) 20 | (add-cash register amount))) 21 | ; 22 | 23 | ; 24 | (def purchases (atom [])) 25 | (defn execute-purchase [purchase] 26 | (swap! purchases conj purchase) 27 | (purchase)) 28 | ; -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/decorator/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.decorator.examples) 2 | 3 | (defn add [a b] (+ a b)) 4 | (defn subtract [a b] (- a b)) 5 | (defn multiply [a b] (* a b)) 6 | (defn divide [a b] (/ a b)) 7 | 8 | (defn make-logger [calc-fn] 9 | (fn [a b] 10 | (let [result (calc-fn a b)] 11 | (println (str "Result is: " result)) 12 | result))) 13 | 14 | (def logging-add (make-logger add)) 15 | (def logging-subtract (make-logger subtract)) 16 | (def logging-multiply (make-logger multiply)) 17 | (def logging-divide (make-logger divide)) 18 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/iterator/higher_order_functions.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.iterator.higher-order-functions) 2 | 3 | (defn sum-sequence [s] 4 | {:pre [(not (empty? s))]} 5 | (reduce + s)) 6 | 7 | (defn prepend-hello [names] 8 | (map (fn [name] (str "Hello, " name)) names)) 9 | 10 | (def vowel? #{\a \e \i \o \u}) 11 | (defn vowels-in-word [word] 12 | (set (filter vowel? word))) 13 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/iterator/lambda_bar_and_grille.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.iterator.lambda-bar-and-grille) 2 | 3 | (def close-zip? #{19123 19103}) 4 | 5 | (defn generate-greetings [people] 6 | (for [{:keys [name address]} people :when (close-zip? (address :zip-code))] 7 | (str "Hello, " name ", and welcome to the Lambda Bar And Grille!"))) 8 | 9 | (defn print-greetings [people] 10 | (for [{:keys [name address]} people :when (close-zip? (address :zip-code))] 11 | (println (str "Hello, " name ", and welcome to the Lambda Bar And Grille!")))) 12 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/javabean/catsanddogslivingtogether.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.javabean.catsanddogslivingtogether) 2 | 3 | (defrecord Cat [color name]) 4 | 5 | (defrecord Dog [color name]) 6 | 7 | (defprotocol NoiseMaker 8 | (make-noise [this])) 9 | 10 | (defrecord NoisyCat [color name] 11 | NoiseMaker 12 | (make-noise [this] (str (:name this) "meows!"))) 13 | 14 | (defrecord NoisyDog [color name] 15 | NoiseMaker 16 | (make-noise [this] (str (:name this) "barks!"))) 17 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/javabean/person.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.javabean.person) 2 | 3 | (def p 4 | {:first-name "John" 5 | :middle-name "Quincy" 6 | :last-name "Adams"}) 7 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/javabean/sidebar.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.javabean.sidebar) 2 | 3 | (def cat {:type :cat 4 | :color "Calico" 5 | :name "Fuzzy McBootings"}) 6 | 7 | (def dog {:type :dog 8 | :color "Brown" 9 | :name "Brown Dog"}) 10 | 11 | (defmulti make-noise (fn [animal] (:type animal))) 12 | (defmethod make-noise :cat [cat] (println (str (:name cat)) "meows!")) 13 | (defmethod make-noise :dog [dog] (println (str (:name dog)) "barks!")) 14 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/nullobject/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.nullobject.examples 2 | (:require [clojure.string :as string])) 3 | 4 | (defn example [x] 5 | (if x 6 | (println "wasn't nil") 7 | (println "was nil"))) 8 | 9 | (defmulti example-mm (fn [x] (nil? x))) 10 | 11 | (defmethod example-mm false [x] (println "wasn't nil")) 12 | (defmethod example-mm true [x] (println "was nil")) 13 | 14 | (def null-person {:first-name "John" :last-name "Doe"}) 15 | (defn fetch-person [people id] 16 | (get id people null-person)) 17 | 18 | (defn person-greeting [person] 19 | (if person 20 | (->> (:first-name person) 21 | string/capitalize 22 | (str "Hello, ")) 23 | "Hello, John")) 24 | 25 | (defn build-person [first-name last-name] 26 | (if (and first-name last-name) 27 | {:first-name first-name :last-name last-name} 28 | {:first-name "John" :last-name "Doe"})) 29 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/strategy/people_example.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.strategy.people-example) 2 | 3 | (defn first-name-valid? [person] 4 | (not (nil? (:first-name person)))) 5 | 6 | (defn full-name-valid? [person] 7 | (and 8 | (not (nil? (:first-name person))) 9 | (not (nil? (:middle-name person))) 10 | (not (nil? (:last-name person))))) 11 | 12 | (defn person-collector [valid?] 13 | (let [valid-people (atom [])] 14 | (fn [person] 15 | (if (valid? person) 16 | (swap! valid-people conj person)) 17 | @valid-people))) 18 | 19 | 20 | (def p1 {:first-name "john" :middle-name "quincy" :last-name "adams"}) 21 | (def p2 {:first-name "mike" :middle-name nil :last-name "adams"}) 22 | (def p3 {:first-name nil :middle-name nil :last-name nil}) -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/RenderingException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class RenderingException extends RuntimeException { 12 | 13 | public RenderingException(Exception e) { 14 | super(e); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/core.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tinyweb.core 2 | (:require [clojure.string :as str]) 3 | (:import (com.mblinn.oo.tinyweb RenderingException ControllerException))) 4 | (defn- render [view model] 5 | (try 6 | (view model) 7 | (catch Exception e (throw (RenderingException. e))))) 8 | (defn- execute-request [http-request handler] 9 | (let [controller (handler :controller) 10 | view (handler :view)] 11 | (try 12 | {:status-code 200 13 | :body 14 | (render 15 | view 16 | (controller http-request))} 17 | (catch ControllerException e {:status-code (.getStatusCode e) :body ""}) 18 | (catch RenderingException e {:status-code 500 19 | :body "Exception while rendering"}) 20 | (catch Exception e (.printStackTrace e) {:status-code 500 :body ""})))) 21 | (defn- apply-filters [filters http-request] 22 | (let [composed-filter (reduce comp (reverse filters))] 23 | (composed-filter http-request))) 24 | (defn tinyweb [request-handlers filters] 25 | (fn [http-request] 26 | (let [filtered-request (apply-filters filters http-request) 27 | path (http-request :path) 28 | handler (request-handlers path)] 29 | (execute-request filtered-request handler)))) 30 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/example.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tinyweb.example 2 | (:use [mbfpp.oo.tinyweb.core]) 3 | (:require [clojure.string :as str])) 4 | 5 | (defn render-greeting [greeting] 6 | (str "

"greeting"

")) 7 | 8 | (defn greeting-view [model] 9 | (let [rendered-greetings (str/join " " (map render-greeting (:greetings model)))] 10 | (str "

Friendly Greetings

" rendered-greetings))) 11 | 12 | (defn logging-filter [http-request] 13 | (println (str "In Logging Filter - request for path: " (:path http-request))) 14 | http-request) 15 | 16 | (defn make-greeting [name] 17 | (let [greetings ["Hello" "Greetings" "Salutations" "Hola"] 18 | greeting-count (count greetings)] 19 | (str (greetings (rand-int greeting-count)) ", " name))) 20 | 21 | (defn handle-greeting [http-request] 22 | {:greetings (map make-greeting (str/split (:body http-request) #","))}) 23 | 24 | (def request-handlers 25 | {"/greeting" {:controller handle-greeting :view greeting-view}}) 26 | (def filters [logging-filter]) 27 | (def tinyweb-instance (tinyweb request-handlers filters)) 28 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/intro.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tinyweb.intro) 2 | 3 | (count [1 2 3 4]) 4 | 5 | (.length "Clojure") -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/stepone.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tinyweb.stepone 2 | (:import (com.mblinn.oo.tinyweb HttpRequest HttpRequest$Builder))) 3 | (defn test-controller [http-request] 4 | {:name (.getBody http-request)}) 5 | (def test-builder (HttpRequest$Builder/newBuilder)) 6 | (def test-http-request (.. test-builder (body "Mike") (path "/say-hello") build)) 7 | (defn test-controller-with-map [http-request] 8 | {:name (http-request :body)}) 9 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tinyweb/steptwo.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tinyweb.steptwo 2 | (:import (com.mblinn.oo.tinyweb RenderingException))) 3 | 4 | (defn test-controller [http-request] 5 | {:name (http-request :body)}) 6 | 7 | (defn test-view [model] 8 | (str "

Hello, " (model :name) "

")) 9 | 10 | (defn- render [view model] 11 | (try 12 | (view model) 13 | (catch Exception e (throw (RenderingException. e))))) 14 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/tm/grade_reporter.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.tm.grade-reporter) 2 | 3 | (defn make-grade-reporter [num-to-letter print-grade-report] 4 | (fn [grades] 5 | (print-grade-report (map num-to-letter grades)))) 6 | 7 | (defn full-grade-converter [grade] 8 | (cond 9 | (and (<= grade 5.0) (> grade 4.0)) "A" 10 | (and (<= grade 4.0) (> grade 3.0)) "B" 11 | (and (<= grade 3.0) (> grade 2.0)) "C" 12 | (and (<= grade 2.0) (> grade 0)) "D" 13 | (= grade 0) "F" 14 | :else "N/A")) 15 | 16 | (defn print-histogram [grades] 17 | (let [grouped (group-by identity grades) 18 | counts (sort (map 19 | (fn [[grade grades]] [grade (count grades)]) 20 | grouped))] 21 | (doseq [[grade num] counts] 22 | (println (str grade ":" (apply str (repeat num "*"))))))) 23 | 24 | (def sample-grades [5.0 4.0 4.4 2.2 3.3 3.5]) 25 | 26 | (def full-grade-reporter (make-grade-reporter full-grade-converter print-histogram)) 27 | 28 | (defn plus-minus-grade-converter [grade] 29 | (cond 30 | (and (<= grade 5.0) (> grade 4.7)) "A" 31 | (and (<= grade 4.7) (> grade 4.3)) "A-" 32 | (and (<= grade 4.3) (> grade 4.0)) "B+" 33 | (and (<= grade 4.0) (> grade 3.7)) "B" 34 | (and (<= grade 3.7) (> grade 3.3)) "B-" 35 | (and (<= grade 3.3) (> grade 3.0)) "C+" 36 | (and (<= grade 3.0) (> grade 2.7)) "C" 37 | (and (<= grade 2.7) (> grade 2.3)) "C" 38 | (and (<= grade 2.3) (> grade 0)) "D" 39 | (= grade 0) "F" 40 | :else "N/A")) 41 | 42 | (defn print-all-grades [grades] 43 | (doseq [grade grades] 44 | (println "Grade is:" grade))) 45 | 46 | (def plus-minus-grade-reporter 47 | (make-grade-reporter plus-minus-grade-converter print-all-grades)) 48 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/oo/visitor/examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.oo.visitor.examples) 2 | 3 | (defprotocol NameExtractor 4 | (extract-name [this] "Extracts a name from a person.")) 5 | 6 | (defrecord SimplePerson [first-name last-name house-num street]) 7 | 8 | (extend-type SimplePerson 9 | NameExtractor 10 | (extract-name [this] 11 | (str (:first-name this) " " (:last-name this)))) 12 | 13 | (defrecord ComplexPerson [name address] 14 | NameExtractor 15 | (extract-name [this] 16 | (str (-> this :name :first) " " (-> this :name :last)))) 17 | 18 | (defprotocol 19 | AddressExtractor 20 | (extract-address [this] "Extracts and address from a person.")) 21 | 22 | (extend-type SimplePerson 23 | AddressExtractor 24 | (extract-address [this] 25 | (str (:house-num this) " " (:street this)))) 26 | 27 | (extend-type ComplexPerson 28 | AddressExtractor 29 | (extract-address [this] 30 | (str (-> this :address :house-num) 31 | " " 32 | (-> this :address :street)))) 33 | 34 | (defmulti test-multimethod (fn [keyword] keyword)) 35 | 36 | (defmethod test-multimethod :foo [a-map] 37 | "foo-method was called") 38 | 39 | (defmethod test-multimethod :bar [a-map] 40 | "bar-method was called") 41 | 42 | (defmulti perimeter (fn [shape] (:shape-name shape))) 43 | (defmethod perimeter :circle [circle] 44 | (* 2 Math/PI (:radius circle))) 45 | (defmethod perimeter :rectangle [rectangle] 46 | (+ (* 2 (:width rectangle)) (* 2 (:height rectangle)))) 47 | 48 | (def some-shapes [{:shape-name :circle :radius 4} 49 | {:shape-name :rectangle :width 2 :height 2}]) 50 | 51 | (defmulti area (fn [shape] (:shape-name shape))) 52 | (defmethod area :circle [circle] 53 | (* Math/PI (:radius circle) (:radius circle))) 54 | (defmethod area :rectangle [rectangle] 55 | (* (:width rectangle) (:height rectangle))) 56 | 57 | (defmethod perimeter :square [square] 58 | (* 4 (:side square))) 59 | (defmethod area :square [square] 60 | (* (:side square) (:side square))) 61 | 62 | (def more-shapes (conj some-shapes 63 | {:shape-name :square :side 4})) 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/rso/closure_comparison.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.rso.closure-comparison) 2 | 3 | (defn make-composed-comparison [& comparisons] 4 | (fn [p1 p2] 5 | (let [results (for [comparison comparisons] (comparison p1 p2)) 6 | first-non-zero-result 7 | (some (fn [result] (if (not (= 0 result)) result nil)) results)] 8 | (if (nil? first-non-zero-result) 9 | 0 10 | first-non-zero-result)))) 11 | 12 | (defn first-name-comparison [p1, p2] 13 | (compare (:first-name p1) (:first-name p2))) 14 | 15 | (defn last-name-comparison [p1 p2] 16 | (compare (:last-name p1) (:last-name p2))) 17 | 18 | (def first-and-last-name-comparison 19 | (make-composed-comparison 20 | first-name-comparison last-name-comparison)) 21 | 22 | (def p1 {:first-name "John" :middle-name "" :last-name "Adams"}) 23 | (def p2 {:first-name "John" :middle-name "Quincy" :last-name "Adams"}) 24 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/rso/closure_example.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.rso.closure-example) 2 | 3 | ; Scope 1 - Top Level 4 | (def foo "first foo") 5 | (def bar "first bar") 6 | (def baz "first baz") 7 | 8 | (defn make-printer [foo bar] ; Scope 2 - Function Arguments 9 | (fn [] 10 | (let [foo "third foo"] ; Scope 3 - Let Statement 11 | (println foo) 12 | (println bar) 13 | (println baz)))) 14 | 15 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/rso/logging.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.rso.logging) 2 | 3 | (defn standard-out [to-log] 4 | (fn [] (println to-log))) 5 | 6 | (defn timestamp-standard-out [to-log] 7 | (fn [] (println (str (System/currentTimeMillis) " : " to-log)))) 8 | 9 | (def history (atom [])) 10 | (defn do-logging [logger] 11 | (swap! history conj logger) 12 | (logger)) 13 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/rso/person.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.rso.person) 2 | 3 | (def p1 {:first-name "Michael" :last-name "Bevilacqua"}) 4 | (def p2 {:first-name "Pedro" :last-name "Vasquez"}) 5 | (def p3 {:first-name "Robert" :last-name "Aarons"}) 6 | 7 | (def people [p3 p2 p1]) 8 | 9 | (sort (fn [p1 p2] (compare (p1 :last-name) (p2 :last-name))) people) 10 | 11 | (sort (fn [p1 p2] (compare (p1 :first-name) (p2 :first-name))) people) 12 | -------------------------------------------------------------------------------- /ClojureExamples/src/mbfpp/rso/person_expanded.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.rso.person-expanded) 2 | 3 | (def p1 {:first-name "Aaron" :middle-name "Jeffrey" :last-name "Smith"}) 4 | (def p2 {:first-name "Aaron" :middle-name "Bailey" :last-name "Zanthar"}) 5 | (def p3 {:first-name "Brian" :middle-name "Adams" :last-name "Smith"}) 6 | (def people [p1 p2 p3]) 7 | (defn complicated-sort [p1 p2] 8 | (let [first-name-compare (compare (p1 :first-name) (p2 :first-name)) 9 | middle-name-compare (compare (p1 :middle-name) (p2 :middle-name)) 10 | last-name-compare (compare (p1 :last-name) (p2 :last-name))] 11 | (cond 12 | (not (= 0 first-name-compare)) first-name-compare 13 | (not (= 0 last-name-compare)) last-name-compare 14 | :else middle-name-compare))) 15 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/fb/composition_examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.fb.composition-examples 2 | (:use [mbfpp.functional.fb.composition-examples]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Append cba appends cba to a string" 6 | (append-cba "foo") => "foocba") 7 | 8 | (fact "Check authorization assumes any non-nil Authorization header is valid" 9 | (let [output (java.io.StringWriter.)] 10 | (binding [*out* output] 11 | (check-authorization request) => request) 12 | (.toString output) => "Valid authorization.\n")) 13 | 14 | (fact "Check authorization assumes any nil Authorization header is invalid" 15 | (let [output (java.io.StringWriter.)] 16 | (binding [*out* output] 17 | (check-authorization {}) => {}) 18 | (.toString output) => "No auth header!\n")) 19 | 20 | (fact "Log fingerprint logs a fingerprint to stdout." 21 | (let [output (java.io.StringWriter.)] 22 | (binding [*out* output] 23 | (log-fingerprint request) => request) 24 | (.toString output) => "FINGERPRINT=fingerprint\n")) 25 | 26 | (fact "Compose filters composes filters together." 27 | (let [filter-one (fn [r] (assoc r :header-one "header one")) 28 | filter-two (fn [r] (assoc r :header-two "header two")) 29 | composed (compose-filters [filter-one filter-two])] 30 | (composed {}) => {:header-one "header one" :header-two "header two"})) -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/fb/discount_builder.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.fb.discount-builder 2 | (:use [mbfpp.functional.fb.discount-builder]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Discount creates functions that calculate 0 percent discounts" 6 | ((discount 0) 100) => 100.0) 7 | 8 | (fact "Discount creates functions that calcuate 100 percent discounts" 9 | ((discount 100) 100) => 0.0) 10 | 11 | (fact "Discount calculates discounts between 1 and 99 percent" 12 | (doseq [percentage (range 1 100)] 13 | ((discount percentage) 100) => (- 100 (* percentage 100 0.01)))) 14 | 15 | (fact "Discounts can only be between 0 and 100" 16 | (discount -1) => (throws AssertionError) 17 | (discount 101) => (throws AssertionError)) -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/fb/partial_examples.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.fb.partial-examples 2 | (:use [mbfpp.functional.fb.partial-examples]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "NY state tax is 0.0645" 6 | (ny-tax 100) => 6.45) 7 | 8 | (fact "PA state tax is 0.045" 9 | (pa-tax 100) => 4.5) -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/fb/selector.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.fb.selector 2 | (:use [mbfpp.functional.fb.selector]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Selector creates functions can extract an element one level deep" 6 | ((selector :foo) {:foo "foo"}) => "foo") 7 | 8 | (fact "Selector creates functions that can extract an element several levels deep" 9 | ((selector :foo :bar :baz) {:foo {:bar {:baz "baz"}}}) => "baz") 10 | 11 | (fact "Selector creates functions that return nil if they don't match" 12 | ((selector :foo) {:bar "bar"}) => nil) -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/mfr/discount.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.mfr.discount 2 | (:use [mbfpp.functional.mfr.discount]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Calculate discount adds a discount of 10% on items twenty dollars or over." 6 | (calculate-discount [20.0 4.5 50.0 15.75 30.0 3.50]) => 10.0 7 | (calculate-discount [4.5 15.75 3.50]) => 0.0 8 | (calculate-discount []) => 0.0) 9 | 10 | (fact "Named and anynomous versions of calculate discount work the same." 11 | (calculate-discount [20.0 4.5 50.0 15.75 30.0 3.50]) => (calculate-discount-namedfn [20.0 4.5 50.0 15.75 30.0 3.50]) 12 | (calculate-discount [4.5 15.75 3.50]) => (calculate-discount-namedfn [4.5 15.75 3.50]) 13 | (calculate-discount []) => (calculate-discount-namedfn [])) 14 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/mr/phases.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.mr.phases 2 | (:use [mbfpp.functional.mr.phases]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "a sequence from liquid-solid-liquid-vapor-plasma-liquid is valid" 6 | (trampoline liquid [:freezing :melting :vaporization :ionization :deionization]) => :valid) 7 | 8 | (fact "a sequence from liquid-plasma is invalid" 9 | (trampoline liquid [:ionization]) => :invalid) 10 | 11 | (fact "the empty sequence is valid" 12 | (trampoline liquid []) => :valid) 13 | 14 | 15 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/functional/tr/names.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.functional.tr.names 2 | (:use [mbfpp.functional.tr.names]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Make people makes people from sequences of first and last names." 6 | (make-people ["firstone" "firsttwo"] ["lastone" "lasttwo"]) => 7 | [{:first "firstone" :last "lastone"} 8 | {:first "firsttwo" :last "lasttwo"}]) 9 | 10 | (fact "Make people and shorter make people workd the same." 11 | (make-people ["firstone" "firsttwo"] ["lastone" "lasttwo"]) => 12 | (shorter-make-people ["firstone" "firsttwo"] ["lastone" "lasttwo"])) -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/oo/command/cash_register.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.oo.command.cash-register 2 | (:use [mbfpp.oo.command.cash-register]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "Cash register's operations all work" 6 | (let [r (make-cash-register)] 7 | @r => 0 8 | (add-cash r 100) => 100 9 | (remove-cash r 50) => 50 10 | (reset r) => 0)) 11 | 12 | (fact "Executing a purchase adds cash to the register." 13 | (let [r (make-cash-register) 14 | p (make-purchase r 100)] 15 | (p) => 100)) 16 | 17 | (fact "execute-purchase executes a purchas and adds it to purchase history." 18 | (let [r (make-cash-register) 19 | p1 (make-purchase r 100) 20 | p2 (make-purchase r 50)] 21 | (execute-purchase p1) 22 | (execute-purchase p2) 23 | @r => 150 24 | (count @purchases) => 2)) 25 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/oo/iterator/higher_order_functions.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.oo.iterator.higher-order-functions 2 | (:use [mbfpp.oo.iterator.higher-order-functions]) 3 | (:use [midje.sweet])) 4 | 5 | (fact "sum-sequence sums a sequence" 6 | (sum-sequence [42, 100, 58]) => 200) 7 | 8 | (fact "sum-sequence doesn't allow the empty sequence" 9 | (sum-sequence []) => (throws AssertionError)) 10 | 11 | (fact "prepend-hello prepends hello to names" 12 | (prepend-hello ["Mike", "Joe", "John"]) => ["Hello, Mike", "Hello, Joe", "Hello, John"] 13 | (prepend-hello [] => [])) 14 | 15 | (fact "vowels-in-word returns a set of vowels in a word" 16 | (vowels-in-word "asdfe") => #{\a \e} 17 | (vowels-in-word "cfg") => #{}) 18 | 19 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/oo/iterator/lambda_bar_and_grille.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.oo.iterator.lambda-bar-and-grille 2 | (:use [mbfpp.oo.iterator.lambda-bar-and-grille]) 3 | (:use [midje.sweet])) 4 | 5 | 6 | (fact "generate-greetings generates a sequence of greetings for people in the correct zip codes" 7 | (generate-greetings [{:name "Mike" :address {:zip-code 19123}} 8 | {:name "John" :address {:zip-code 19103}} 9 | {:name "Jill" :address {:zip-code 19098}}]) => 10 | ["Hello, Mike, and welcome to the Lambda Bar And Grille!" 11 | "Hello, John, and welcome to the Lambda Bar And Grille!"]) 12 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/oo/javabean/catsanddogslivingtogether.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.oo.javabean.catsanddogslivingtogether 2 | (:use [mbfpp.oo.javabean.catsanddogslivingtogether]) 3 | (:use [midje.sweet]) 4 | (:import [mbfpp.oo.javabean.catsanddogslivingtogether NoisyCat NoisyDog])) 5 | 6 | (fact "Cats meow" 7 | (let [output (java.io.StringWriter.)] 8 | (binding [*out* output] 9 | (make-noise (NoisyCat. "Tabby" "Puss"))) 10 | (.toString output) => "Puss meows!\n")) 11 | 12 | (fact "Dogs bark" 13 | (let [output (java.io.StringWriter.)] 14 | (binding [*out* output] 15 | (make-noise (NoisyDog. "Black" "Woofy"))) 16 | (.toString output) => "Woofy barks!\n")) 17 | 18 | -------------------------------------------------------------------------------- /ClojureExamples/test/mbfpp/test/oo/tinyweb/core.clj: -------------------------------------------------------------------------------- 1 | (ns mbfpp.test.oo.tinyweb.core 2 | (:use [mbfpp.oo.tinyweb.core]) 3 | (:use [midje.sweet]) 4 | (:import (com.mblinn.oo.tinyweb RenderingException ControllerException))) 5 | 6 | (defn hello-controller [http-request] 7 | {:name (http-request :body)}) 8 | 9 | (defn hello-view [model] 10 | (str "

Hello, " (model :name) "

")) 11 | 12 | (defn error-controller [http-request] 13 | (throw (ControllerException. (Integer. 503)))) 14 | 15 | (defn runtime-error-controller [http-request] 16 | (throw (RuntimeException.))) 17 | 18 | (defn error-view [model] 19 | (throw (RuntimeException.))) 20 | 21 | (def request-handlers 22 | {"/hello" {:controller hello-controller 23 | :view hello-view} 24 | "/error-controller" {:controller error-controller 25 | :view hello-view} 26 | "/runtime-error-controller" {:controller runtime-error-controller 27 | :view hello-view} 28 | "/error-view" {:controller hello-controller 29 | :view error-view}}) 30 | 31 | (defn filter-one [http-request] 32 | (assoc 33 | http-request 34 | :body (str "a" (:body http-request)))) 35 | 36 | (defn filter-two [http-request] 37 | (assoc 38 | http-request 39 | :body (str "b" (:body http-request)))) 40 | 41 | (fact "Tinyweb should return an http request with a 200 status and body created by the controller and view corresponding to the request path." 42 | (let [tw (tinyweb request-handlers []) 43 | http-request {:path "/hello" :body "Mike" :headers {}}] 44 | (tw http-request) => {:status-code 200 :body "

Hello, Mike

"})) 45 | 46 | (fact "Tinyweb applies filters in the order they're specified." 47 | (let [tw (tinyweb request-handlers [filter-one filter-two]) 48 | http-request {:path "/hello" :body "" :headers {}}] 49 | (tw http-request) => {:status-code 200 :body "

Hello, ab

"})) 50 | 51 | (fact "When a controller throws a ControllerException, Tinyweb returns the statuscode included in it." 52 | (let [tw (tinyweb request-handlers []) 53 | http-request {:path "/error-controller" :body ""}] 54 | (tw http-request) => {:status-code 503 :body ""})) 55 | 56 | (fact "When a controller throws an exception other than a ControllerException, Tinyweb returns a 500 status code." 57 | (let [tw (tinyweb request-handlers []) 58 | http-request {:path "/runtime-error-controller" :body ""}] 59 | (tw http-request) => {:status-code 500 :body ""})) 60 | 61 | (fact "When view code throws an exception, a 500 response is returned." 62 | (let [tw (tinyweb request-handlers []) 63 | http-request {:path "/error-view" :body ""}] 64 | (tw http-request) => {:status-code 500 :body "Exception while rendering"})) 65 | 66 | -------------------------------------------------------------------------------- /JavaExamples/build.sbt: -------------------------------------------------------------------------------- 1 | name := "JavaExamples" 2 | 3 | version := "1.0" 4 | 5 | organization := "com.mblinn" 6 | 7 | libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.3" % "test" 8 | 9 | libraryDependencies += "com.novocode" % "junit-interface" % "0.9" % "test" 10 | 11 | testOptions += Tests.Argument(TestFrameworks.JUnit, "-q", "-v") 12 | -------------------------------------------------------------------------------- /JavaExamples/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1") 2 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/ex/recursion/RecursionExample.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.ex.recursion; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class RecursionExample { 15 | 16 | public static void main(String[] args) { 17 | List list = new ArrayList(); 18 | list.add(1); 19 | list.add(2); 20 | list.add(3); 21 | System.out.println(addList(list)); 22 | } 23 | 24 | 25 | public static Integer addList(List list) { 26 | // if the list is only one element long, return that element. 27 | if (list.size() == 1) { 28 | return list.get(0); 29 | } 30 | // otherwise, return the result of adding the first item in the list, 31 | // to the rest of the list added together 32 | else { 33 | Integer first = list.get(0); 34 | List rest = list.subList(1, list.size()); 35 | return first + addList(rest); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/ex/repeating/VowelFilter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.ex.repeating; 10 | 11 | import java.util.Collection; 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | 15 | public class VowelFilter { 16 | private static final Set vowels = new HashSet(); 17 | static { 18 | vowels.add('a'); 19 | vowels.add('e'); 20 | vowels.add('i'); 21 | vowels.add('o'); 22 | vowels.add('u'); 23 | } 24 | 25 | public Collection vowelsInWord(String word) { 26 | Set vowelsInString = new HashSet(); 27 | 28 | for (Character character : word.toLowerCase().toCharArray()) { 29 | if (vowels.contains(character)) { 30 | vowelsInString.add(character); 31 | } 32 | } 33 | 34 | return vowelsInString; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/functional/tailrecursion/Sum.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.functional.tailrecursion; 10 | 11 | public class Sum { 12 | 13 | public static void main(String[] args) { 14 | System.out.println("sum: " + sum(10)); 15 | System.out.println("sumRecursive: " + sumRecursive(10)); 16 | System.out.println("sumTailRecursive: " + sumTailRecursive(10, 0)); 17 | } 18 | 19 | public static int sum(int upTo) { 20 | int sum = 0; 21 | for (int i = 0; i <= upTo; i++) 22 | sum += i; 23 | return sum; 24 | } 25 | 26 | 27 | public static int sumRecursive(int upTo) { 28 | if (upTo == 0) 29 | return 0; 30 | else 31 | return upTo + sumRecursive(upTo - 1); 32 | } 33 | 34 | 35 | public static int sumTailRecursive(int upTo, int currentSum) { 36 | if (upTo == 0) 37 | return currentSum; 38 | else 39 | return sumTailRecursive(upTo - 1, currentSum + upTo); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/functional/coo/Examples.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.functional.coo; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class Examples { 15 | 16 | public static void main(String[] args){ 17 | List names = new ArrayList(); 18 | names.add("Michael Bevilacqua Linn"); 19 | names.get(0).toUpperCase(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/intro/FilterOdds.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.intro; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class FilterOdds { 15 | 16 | public List filterOdds(List list) { 17 | List filteredList = new ArrayList(); 18 | for (Integer current : list) { 19 | if (isOdd(current)) { 20 | filteredList.add(current); 21 | } 22 | } 23 | return filteredList; 24 | } 25 | private boolean isOdd(Integer integer) { 26 | return 0 != integer % 2; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/command/CashRegister.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.command; 10 | 11 | public class CashRegister { 12 | private Integer total; 13 | 14 | public CashRegister(Integer startingTotal) { 15 | total = startingTotal; 16 | } 17 | 18 | public void addCash(Integer toAdd) { 19 | total += toAdd; 20 | } 21 | 22 | public Integer getTotal() { 23 | return total; 24 | } 25 | 26 | public void reset() { 27 | total = 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/command/Command.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.command; 10 | 11 | public interface Command { 12 | public void execute(); 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/command/Purchase.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.command; 10 | 11 | public class Purchase implements Command { 12 | private CashRegister cashRegister; 13 | private Integer amount; 14 | 15 | public Purchase(CashRegister cashRegister, Integer amount) { 16 | this.cashRegister = cashRegister; 17 | this.amount = amount; 18 | } 19 | 20 | @Override 21 | public void execute() { 22 | cashRegister.addCash(amount); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/command/PurchaseInvoker.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.command; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class PurchaseInvoker { 15 | private List executedPurchases = new ArrayList(); 16 | 17 | public void executePurchase(Command purchase) { 18 | purchase.execute(); 19 | executedPurchases.add(purchase); 20 | } 21 | 22 | public List getPurchaseHistory() { 23 | return executedPurchases; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/command/RegisterClient.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.command; 10 | 11 | import java.util.List; 12 | 13 | public class RegisterClient { 14 | private static CashRegister cashRegister = new CashRegister(0); 15 | private static PurchaseInvoker purchaseInvoker = new PurchaseInvoker(); 16 | 17 | public static void main(String[] args) { 18 | Command purchase1 = new Purchase(cashRegister, 100); 19 | Command purchase2 = new Purchase(cashRegister, 50); 20 | 21 | // Invoke commands, check register total. 22 | purchaseInvoker.executePurchase(purchase1); 23 | purchaseInvoker.executePurchase(purchase2); 24 | System.out.println("After purchases: " + cashRegister.getTotal()); 25 | 26 | // Replay purchases 27 | cashRegister.reset(); 28 | System.out.println("Register reset to 0"); 29 | List purchases = purchaseInvoker.getPurchaseHistory(); 30 | for (Command purchase : purchases) { 31 | purchase.execute(); 32 | } 33 | System.out.println("After replay: " + cashRegister.getTotal()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/FavoritesService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di; 10 | 11 | public class FavoritesService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/MovieDao.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di; 10 | 11 | public class MovieDao { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/MovieService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di; 10 | public class MovieService { 11 | 12 | private MovieDao movieDao; 13 | private FavoritesService favoritesService; 14 | public MovieService(MovieDao movieDao, FavoritesService favoritesService){ 15 | this.movieDao = movieDao; 16 | this.favoritesService = favoritesService; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/DecoratedMovie.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class DecoratedMovie { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/FavoriteVideosService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class FavoriteVideosService { 12 | 13 | private VideoService videoService; 14 | private FavoritesService favoritesService; 15 | 16 | private FavoriteVideosService(VideoService videoService, 17 | FavoritesService favoritesService){ 18 | this.videoService = videoService; 19 | this.favoritesService = favoritesService; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/FavoritesService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class FavoritesService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/Movie.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class Movie { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/MovieDao.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class MovieDao { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/MovieService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | import java.util.List; 12 | 13 | public abstract class MovieService { 14 | 15 | private FavoriteVideosService favoriteVideosService; 16 | private MovieDao movieDao; 17 | 18 | public MovieService(FavoriteVideosService favoriteVideosService, 19 | MovieDao movieDao) { 20 | this.favoriteVideosService = favoriteVideosService; 21 | this.movieDao = movieDao; 22 | } 23 | 24 | public abstract List getFavoritesMovies(); 25 | public abstract Movie getMovie(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/di/ex1/VideoService.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.di.ex1; 10 | 11 | public class VideoService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/ComplicatedNameComparator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.Comparator; 12 | 13 | 14 | public class ComplicatedNameComparator implements Comparator { 15 | public int compare(PersonExpanded p1, PersonExpanded p2) { 16 | 17 | int firstNameCompare = 18 | p1.getFirstName().compareTo(p2.getFirstName()); 19 | int lastNameCompare = p1.getLastName().compareTo(p2.getLastName()); 20 | int middleNameCompare = p1.getMidName().compareTo(p2.getMidName()); 21 | 22 | if (0 != firstNameCompare) 23 | return firstNameCompare; 24 | else if (0 != lastNameCompare) 25 | return lastNameCompare; 26 | else 27 | return middleNameCompare; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/ComposedComparator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.Comparator; 12 | 13 | public class ComposedComparator implements Comparator { 14 | 15 | private Comparator[] comparators; 16 | 17 | public ComposedComparator(Comparator... comparators) { 18 | this.comparators = comparators; 19 | } 20 | 21 | @Override 22 | public int compare(T o1, T o2) { 23 | for (Comparator comparator : comparators) { 24 | int result = comparator.compare(o1, o2); 25 | if (result != 0) 26 | return result; 27 | } 28 | return 0; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/Harness.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.Comparator; 12 | 13 | 14 | public class Harness { 15 | 16 | public static void main(String[] args) { 17 | Comparator firstAndLastNameComparator = 18 | new ComposedComparator( 19 | new FirstNameComparator(), 20 | new LastNameComparator()); 21 | 22 | PersonExpanded personOne = new PersonExpanded("John", "", "Adams"); 23 | PersonExpanded personTwo = new PersonExpanded("John", "Quincy", "Adams"); 24 | 25 | System.out 26 | .println(firstAndLastNameComparator.compare(personOne, personTwo)); 27 | } 28 | } 29 | 30 | class FirstNameComparator implements Comparator { 31 | @Override 32 | public int compare(PersonExpanded personOne, PersonExpanded personTwo) { 33 | return personOne.getFirstName().compareTo(personTwo.getFirstName()); 34 | } 35 | } 36 | 37 | class LastNameComparator implements Comparator { 38 | @Override 39 | public int compare(PersonExpanded personOne, PersonExpanded personTwo) { 40 | return personOne.getLastName().compareTo(personTwo.getLastName()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/Person.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | public class Person implements Comparable { 12 | private String firstName; 13 | private String lastName; 14 | 15 | public Person(String firstName, String lastName) { 16 | this.firstName = firstName; 17 | this.lastName = lastName; 18 | } 19 | 20 | public String getFirstName() { 21 | return firstName; 22 | } 23 | 24 | public void setFirstName(String firstName) { 25 | this.firstName = firstName; 26 | } 27 | 28 | public String getLastName() { 29 | return lastName; 30 | } 31 | 32 | public void setLastName(String lastName) { 33 | this.lastName = lastName; 34 | } 35 | 36 | @Override 37 | // Implements the Comparable interface. 38 | public int compareTo(Person otherPerson) { 39 | return this.lastName.compareTo(otherPerson.lastName); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return firstName + " " + lastName; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/PersonComplicatedSort.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | 16 | public class PersonComplicatedSort { 17 | 18 | public static void main(String[] args) { 19 | List people = new ArrayList(); 20 | people.add(new PersonExpanded("Aaron", "Jeffrey", "Smith")); 21 | people.add(new PersonExpanded("Aaron", "Bailey", "Zanthar")); 22 | people.add(new PersonExpanded("Brian", "Adams", "Smith")); 23 | 24 | Collections.sort(people, new ComplicatedNameComparator()); 25 | 26 | for (PersonExpanded person : people) { 27 | System.out.println(person); 28 | } 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/PersonExpanded.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | public class PersonExpanded implements Comparable { 12 | private String firstName; 13 | private String lastName; 14 | private String midName; 15 | 16 | public PersonExpanded(String firstName, String midName, String lastName) { 17 | this.firstName = firstName; 18 | this.lastName = lastName; 19 | this.midName = midName; 20 | } 21 | 22 | public String getFirstName() { 23 | return firstName; 24 | } 25 | 26 | public void setFirstName(String firstName) { 27 | this.firstName = firstName; 28 | } 29 | 30 | public String getLastName() { 31 | return lastName; 32 | } 33 | 34 | public void setLastName(String lastName) { 35 | this.lastName = lastName; 36 | } 37 | 38 | public String getMidName() { 39 | return midName; 40 | } 41 | 42 | public void setMidName(String middleName) { 43 | this.midName = middleName; 44 | } 45 | 46 | @Override 47 | public int compareTo(PersonExpanded otherPerson) { 48 | return this.lastName.compareTo(otherPerson.lastName); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return firstName + " " + midName + " " + lastName; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/PersonFirstNameSort.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.Comparator; 14 | import java.util.List; 15 | 16 | public class PersonFirstNameSort { 17 | public static void main(String[] args) { 18 | Person p1 = new Person("Mike", "Bevilacqua"); 19 | Person p2 = new Person("Pedro", "Vasquez"); 20 | Person p3 = new Person("Robert", "Aarons"); 21 | 22 | List people = new ArrayList(); 23 | people.add(p1); 24 | people.add(p2); 25 | people.add(p3); 26 | 27 | Collections.sort(people, new Comparator() { 28 | public int compare(Person p1, Person p2) { 29 | return p1.getFirstName().compareTo(p2.getFirstName()); 30 | } 31 | }); 32 | 33 | for (Person person : people) { 34 | System.out.println(person); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/fi/PersonNaturalSort.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | public class PersonNaturalSort { 16 | 17 | public static void main(String[] args) { 18 | Person p1 = new Person("Mike", "Bevilacqua"); 19 | Person p2 = new Person("Pedro", "Vasquez"); 20 | Person p3 = new Person("Robert", "Aarons"); 21 | 22 | List people = new ArrayList(); 23 | people.add(p1); 24 | people.add(p2); 25 | people.add(p3); 26 | 27 | Collections.sort(people); 28 | 29 | for (Person person : people) { 30 | System.out.println(person); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/tm/FullGradeReporter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tm; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.SortedMap; 15 | import java.util.TreeMap; 16 | 17 | public class FullGradeReporter extends GradeReporterTemplate { 18 | @Override 19 | public String numToLetter(Double grade) { 20 | if (grade <= 5.0 && grade > 4.0) 21 | return "A"; 22 | else if (grade <= 4.0 && grade > 3.0) 23 | return "B"; 24 | else if (grade <= 3.0 && grade > 2.0) 25 | return "C"; 26 | else if (grade <= 2.0 && grade > 0.0) 27 | return "D"; 28 | else if (grade == 0.0) 29 | return "F"; 30 | else 31 | return "N/A"; 32 | } 33 | 34 | 35 | @Override 36 | protected void printGradeReport(List grades) { 37 | SortedMap gradeCounts = new TreeMap(); 38 | 39 | for (String grade : grades) { 40 | Integer currentGradeCount = gradeCounts.get(grade); 41 | if (null == currentGradeCount) 42 | gradeCounts.put(grade, 1); 43 | else 44 | gradeCounts.put(grade, currentGradeCount + 1); 45 | } 46 | 47 | for (Map.Entry gradeCount : gradeCounts.entrySet()) { 48 | StringBuffer bar = new StringBuffer(); 49 | for (int i = 0; i < gradeCount.getValue(); i++) 50 | bar.append("*"); 51 | System.out.printf("%s: %s\n", gradeCount.getKey(), bar); 52 | } 53 | } 54 | 55 | 56 | public static void main(String[] args) { 57 | GradeReporterTemplate gradeReporter = new FullGradeReporter(); 58 | List grades = Arrays.asList(new Double[] { 5.0, 4.0, 4.4, 2.2, 3.3, 59 | 3.5 }); 60 | gradeReporter.reportGrades(grades); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/tm/GradeReporterTemplate.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tm; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public abstract class GradeReporterTemplate { 15 | 16 | public void reportGrades(List grades) { 17 | List convertedGrades = new ArrayList(); 18 | for (Double grade : grades) { 19 | convertedGrades.add(numToLetter(grade)); 20 | } 21 | printGradeReport(convertedGrades); 22 | } 23 | 24 | protected abstract String numToLetter(Double grade); 25 | 26 | protected abstract void printGradeReport(List grades); 27 | } 28 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/mbfpp/oo/tm/PlusMinusGradeReporter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tm; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | public class PlusMinusGradeReporter extends GradeReporterTemplate { 15 | @Override 16 | protected String numToLetter(Double grade) { 17 | if (grade <= 5.0 && grade > 4.7) 18 | return "A"; 19 | else if (grade <= 4.7 && grade > 4.3) 20 | return "A-"; 21 | else if (grade <= 4.3 && grade > 4.0) 22 | return "B+"; 23 | else if (grade <= 4.0 && grade > 3.7) 24 | return "B"; 25 | else if (grade <= 3.7 && grade > 3.3) 26 | return "B-"; 27 | else if (grade <= 3.3 && grade > 3.0) 28 | return "C+"; 29 | else if (grade <= 3.0 && grade > 2.7) 30 | return "C"; 31 | else if (grade <= 2.7 && grade > 2.3) 32 | return "C-"; 33 | else if (grade <= 2.3 && grade > 0.0) 34 | return "D"; 35 | else if (grade == 0.0) 36 | return "F"; 37 | else 38 | return "N/A"; 39 | } 40 | 41 | 42 | @Override 43 | protected void printGradeReport(List grades) { 44 | for (String grade : grades) { 45 | System.out.println("Grade is: " + grade); 46 | } 47 | } 48 | 49 | 50 | public static void main(String[] args) { 51 | GradeReporterTemplate gradeReporter = new PlusMinusGradeReporter(); 52 | List grades = Arrays.asList(new Double[] { 5.0, 4.0, 4.4, 2.2, 3.3, 53 | 3.5 }); 54 | gradeReporter.reportGrades(grades); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/iterator/Address.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.iterator; 10 | 11 | public class Address { 12 | 13 | private Integer zipCode; 14 | 15 | // Other fields elided for the sake of brevity. 16 | 17 | public Integer getZipCode() { 18 | return zipCode; 19 | } 20 | 21 | public void setZipCode(Integer zipCode) { 22 | this.zipCode = zipCode; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/iterator/HigherOrderFunctions.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.iterator; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | public class HigherOrderFunctions { 17 | 18 | public static Integer sumSequence(List sequence) { 19 | Integer sum = 0; 20 | for (Integer num : sequence) { 21 | sum += num; 22 | } 23 | return sum; 24 | } 25 | 26 | 27 | public static List prependHello(List names) { 28 | List prepended = new ArrayList(); 29 | for (String name : names) { 30 | prepended.add("Hello, " + name); 31 | } 32 | return prepended; 33 | } 34 | 35 | 36 | public static Set vowelsInWord(String word) { 37 | 38 | Set vowelsInWord = new HashSet(); 39 | 40 | for (Character character : word.toLowerCase().toCharArray()) { 41 | if (isVowel(character)) { 42 | vowelsInWord.add(character); 43 | } 44 | } 45 | 46 | return vowelsInWord; 47 | } 48 | 49 | private static Boolean isVowel(Character c){ 50 | Set vowels = new HashSet(); 51 | vowels.add('a'); 52 | vowels.add('e'); 53 | vowels.add('i'); 54 | vowels.add('o'); 55 | vowels.add('u'); 56 | return vowels.contains(c); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/iterator/Person.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.iterator; 10 | 11 | public class Person { 12 | 13 | private String name; 14 | private Address address; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public Address getAddress() { 25 | return address; 26 | } 27 | 28 | public void setAddress(Address address) { 29 | this.address = address; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/iterator/TheLambdaBarAndGrille.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.iterator; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | public class TheLambdaBarAndGrille { 17 | 18 | public Map> peopleByZip(List people) { 19 | Map> closePeople = 20 | new HashMap>(); 21 | 22 | for (Person person : people) { 23 | Integer zipCode = person.getAddress().getZipCode(); 24 | if (isCloseZip(zipCode)){ 25 | List peopleForZip = 26 | closePeople.get(zipCode); 27 | closePeople.put(zipCode, 28 | addPerson(peopleForZip, person)); 29 | } 30 | } 31 | 32 | return closePeople; 33 | } 34 | 35 | private List addPerson(List people, Person person) { 36 | if (null == people) 37 | people = new ArrayList(); 38 | people.add(person.getName()); 39 | return people; 40 | } 41 | private Boolean isCloseZip(Integer zipCode) { 42 | return zipCode == 19123 || zipCode == 19103; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/javabean/ImmutablePerson.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.javabean; 10 | 11 | public class ImmutablePerson { 12 | 13 | private final String firstName; 14 | private final String lastName; 15 | 16 | public String getFirstName() { 17 | return firstName; 18 | } 19 | 20 | public String getLastName() { 21 | return lastName; 22 | } 23 | 24 | private ImmutablePerson(Builder builder){ 25 | firstName = builder.firstName; 26 | lastName = builder.lastName; 27 | } 28 | 29 | public static class Builder { 30 | private String firstName; 31 | private String lastName; 32 | 33 | public Builder firstName(String firstName) { 34 | this.firstName = firstName; 35 | return this; 36 | } 37 | 38 | public Builder lastName(String lastName) { 39 | this.lastName = lastName; 40 | return this; 41 | } 42 | 43 | public ImmutablePerson build() { 44 | return new ImmutablePerson(this); 45 | } 46 | } 47 | 48 | public static Builder newBuilder() { 49 | return new Builder(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/javabean/Person.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.javabean; 10 | 11 | public class Person { 12 | 13 | private String firstName; 14 | private String lastName; 15 | 16 | public String getFirstName() { 17 | return firstName; 18 | } 19 | 20 | public void setFirstName(String firstName) { 21 | this.firstName = firstName; 22 | } 23 | 24 | public String getLastName() { 25 | return lastName; 26 | } 27 | 28 | public void setLastName(String lastName) { 29 | this.lastName = lastName; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/javabean/PersonHarness.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.javabean; 10 | 11 | public class PersonHarness { 12 | 13 | public static void main(String[] args) { 14 | ImmutablePerson.Builder b = ImmutablePerson.newBuilder(); 15 | ImmutablePerson p = b.firstName("Peter").lastName("Jones").build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/nullobject/NullPerson.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.nullobject; 10 | 11 | class NullPerson implements Person { 12 | 13 | public String getFirstName() { 14 | return "John"; 15 | } 16 | 17 | public void setFirstName(String firstName) { 18 | } 19 | 20 | public String getLastName() { 21 | return "Doe"; 22 | } 23 | 24 | public void setLastName(String lastName) { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/nullobject/Person.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.nullobject; 10 | 11 | interface Person { 12 | public String getFirstName(); 13 | 14 | public void setFirstName(String firstName); 15 | 16 | public String getLastName(); 17 | 18 | public void setLastName(String lastName); 19 | } -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/nullobject/PersonExample.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.nullobject; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | public class PersonExample { 15 | private Map people; 16 | 17 | public PersonExample() { 18 | people = new HashMap(); 19 | } 20 | 21 | public Person fetchPerson(Integer id) { 22 | Person person = people.get(id); 23 | if (null != person) 24 | return person; 25 | else 26 | return new NullPerson(); 27 | } 28 | // Code to add/remove people 29 | 30 | public Person buildPerson(String firstName, String lastName){ 31 | if(null != firstName && null != lastName) 32 | return new RealPerson(firstName, lastName); 33 | else 34 | return new NullPerson(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/nullobject/RealPerson.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.nullobject; 10 | 11 | class RealPerson implements Person { 12 | private String firstName; 13 | private String lastName; 14 | 15 | public RealPerson(String firstName, String lastName) { 16 | this.firstName = firstName; 17 | this.lastName = lastName; 18 | } 19 | 20 | public String getFirstName() { 21 | return firstName; 22 | } 23 | 24 | public void setFirstName(String firstName) { 25 | this.firstName = firstName; 26 | } 27 | 28 | public String getLastName() { 29 | return lastName; 30 | } 31 | 32 | public void setLastName(String lastName) { 33 | this.lastName = lastName; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/strategy/FirstNameValidator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | public class FirstNameValidator implements PersonValidator { 12 | @Override 13 | public boolean validate(Person person) { 14 | return person.getFirstName() != null; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/strategy/FullNameValidator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | public class FullNameValidator implements PersonValidator { 12 | @Override 13 | public boolean validate(Person person) { 14 | return person.getFirstName() != null 15 | && person.getMiddleName() != null 16 | && person.getLastName() != null; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/strategy/Person.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | public class Person { 12 | private String firstName; 13 | private String lastName; 14 | private String middleName; 15 | 16 | public Person(String firstName, String middleName, String lastName) { 17 | this.firstName = firstName; 18 | this.lastName = lastName; 19 | this.middleName = middleName; 20 | } 21 | 22 | public String getFirstName() { 23 | return firstName; 24 | } 25 | 26 | public void setFirstName(String firstName) { 27 | this.firstName = firstName; 28 | } 29 | 30 | public String getLastName() { 31 | return lastName; 32 | } 33 | 34 | public void setLastName(String lastName) { 35 | this.lastName = lastName; 36 | } 37 | 38 | public String getMiddleName() { 39 | return middleName; 40 | } 41 | 42 | public void setMiddleName(String middleName) { 43 | this.middleName = middleName; 44 | } 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/strategy/PersonCollector.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class PersonCollector { 15 | private PersonValidator personValidator; 16 | private List validPeople; 17 | 18 | public PersonCollector(PersonValidator personValidator) { 19 | this.personValidator = personValidator; 20 | this.validPeople = new ArrayList(); 21 | } 22 | 23 | public void addPerson(Person person) { 24 | if (personValidator.validate(person)) 25 | validPeople.add(person); 26 | } 27 | 28 | public List getValidPeople() { 29 | return validPeople; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/strategy/PersonValidator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | public interface PersonValidator { 12 | public boolean validate(Person person); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/Controller.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public interface Controller { 12 | public HttpResponse handleRequest(HttpRequest httpRequest); 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/ControllerException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class ControllerException extends RuntimeException { 12 | private Integer statusCode; 13 | 14 | public ControllerException(Integer statusCode) { 15 | this.statusCode = statusCode; 16 | } 17 | 18 | public Integer getStatusCode() { 19 | return statusCode; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/Filter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public interface Filter { 12 | public HttpRequest doFilter(HttpRequest request); 13 | } 14 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/HttpRequest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.Collections; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class HttpRequest { 16 | private Map headers; 17 | private String body; 18 | private String path; 19 | 20 | public Map getHeaders() { 21 | return headers; 22 | } 23 | 24 | public String getBody() { 25 | return body; 26 | } 27 | 28 | public String getPath() { 29 | return path; 30 | } 31 | 32 | private HttpRequest(Builder builder) { 33 | this.headers = Collections.unmodifiableMap(builder.headers); 34 | this.body = builder.body; 35 | this.path = builder.path; 36 | } 37 | 38 | public static class Builder { 39 | private Map headers; 40 | private String body; 41 | private String path; 42 | 43 | private Builder() { 44 | headers = new HashMap(); 45 | } 46 | 47 | public Builder addHeader(String name, String value) { 48 | headers.put(name, value); 49 | return this; 50 | } 51 | 52 | public Builder body(String body) { 53 | this.body = body; 54 | return this; 55 | } 56 | 57 | public Builder path(String path) { 58 | this.path = path; 59 | return this; 60 | } 61 | 62 | public HttpRequest build() { 63 | return new HttpRequest(this); 64 | } 65 | 66 | public static Builder newBuilder() { 67 | return new Builder(); 68 | } 69 | 70 | public static Builder builderFrom(HttpRequest request) { 71 | Builder builder = new Builder(); 72 | builder.path(request.getPath()); 73 | builder.body(request.getBody()); 74 | 75 | Map headers = request.getHeaders(); 76 | for (String headerName : headers.keySet()) 77 | builder.addHeader(headerName, 78 | headers.get(headerName)); 79 | 80 | return builder; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/HttpResponse.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class HttpResponse { 12 | private final String body; 13 | private final Integer responseCode; 14 | 15 | public String getBody() { 16 | return body; 17 | } 18 | 19 | public Integer getResponseCode() { 20 | return responseCode; 21 | } 22 | 23 | private HttpResponse(Builder builder) { 24 | body = builder.body; 25 | responseCode = builder.responseCode; 26 | } 27 | 28 | public static class Builder { 29 | private String body; 30 | private Integer responseCode; 31 | 32 | public Builder body(String body) { 33 | this.body = body; 34 | return this; 35 | } 36 | 37 | public Builder responseCode(Integer responseCode) { 38 | this.responseCode = responseCode; 39 | return this; 40 | } 41 | 42 | public HttpResponse build() { 43 | return new HttpResponse(this); 44 | } 45 | 46 | public static Builder newBuilder() { 47 | return new Builder(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/RenderingException.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | public class RenderingException extends RuntimeException { 12 | 13 | public RenderingException(Exception e) { 14 | super(e); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/RenderingStrategy.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public interface RenderingStrategy { 15 | 16 | public String renderView(Map> model); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/StrategyView.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class StrategyView implements View { 15 | 16 | private RenderingStrategy viewRenderer; 17 | 18 | public StrategyView(RenderingStrategy viewRenderer) { 19 | this.viewRenderer = viewRenderer; 20 | } 21 | 22 | @Override 23 | public String render(Map> model) { 24 | try { 25 | return viewRenderer.renderView(model); 26 | } catch (Exception e) { 27 | throw new RenderingException(e); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/TemplateController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public abstract class TemplateController implements Controller { 15 | private View view; 16 | public TemplateController(View view) { 17 | this.view = view; 18 | } 19 | 20 | public HttpResponse handleRequest(HttpRequest request) { 21 | Integer responseCode = 200; 22 | String responseBody = ""; 23 | 24 | try { 25 | Map> model = doRequest(request); 26 | responseBody = view.render(model); 27 | } catch (ControllerException e) { 28 | responseCode = e.getStatusCode(); 29 | } catch (RenderingException e) { 30 | responseCode = 500; 31 | responseBody = "Exception while rendering."; 32 | } catch (Exception e) { 33 | responseCode = 500; 34 | } 35 | 36 | return HttpResponse.Builder.newBuilder().body(responseBody) 37 | .responseCode(responseCode).build(); 38 | } 39 | protected abstract Map> doRequest(HttpRequest request); 40 | } 41 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/TinyWeb.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public class TinyWeb { 15 | private Map controllers; 16 | private List filters; 17 | 18 | public TinyWeb(Map controllers, List filters) { 19 | this.controllers = controllers; 20 | this.filters = filters; 21 | } 22 | 23 | public HttpResponse handleRequest(HttpRequest httpRequest) { 24 | 25 | HttpRequest currentRequest = httpRequest; 26 | for (Filter filter : filters) { 27 | currentRequest = filter.doFilter(currentRequest); 28 | } 29 | 30 | Controller controller = controllers.get(currentRequest.getPath()); 31 | 32 | if (null == controller) 33 | return null; 34 | 35 | return controller.handleRequest(currentRequest); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/View.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public interface View { 15 | public String render(Map> model); 16 | } 17 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/ExampleHarness.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | import com.mblinn.oo.tinyweb.StrategyView; 18 | import com.mblinn.oo.tinyweb.Controller; 19 | import com.mblinn.oo.tinyweb.Filter; 20 | import com.mblinn.oo.tinyweb.HttpRequest; 21 | import com.mblinn.oo.tinyweb.HttpResponse; 22 | import com.mblinn.oo.tinyweb.TinyWeb; 23 | 24 | public class ExampleHarness { 25 | 26 | public static void main(String[] args){ 27 | 28 | TinyWeb tinyWeb = new TinyWeb(makeRoutes(), makeFilters()); 29 | 30 | HttpRequest testRequest = HttpRequest.Builder.newBuilder() 31 | .path("greeting/") 32 | .body("Mike,Joe,John,Steve") 33 | .addHeader("X-Example", "exampleHeader") 34 | .build(); 35 | 36 | HttpResponse testResponse = tinyWeb.handleRequest(testRequest); 37 | 38 | System.out.println("responseCode: " + testResponse.getResponseCode()); 39 | System.out.println("responseBody: "); 40 | System.out.println(testResponse.getBody()); 41 | } 42 | 43 | private static Map makeRoutes(){ 44 | GreetingRenderingStrategy viewRenderer = new GreetingRenderingStrategy(); 45 | StrategyView greetingView = new StrategyView(viewRenderer); 46 | GreetingController greetingController = new GreetingController(greetingView); 47 | 48 | Map controllers = new HashMap(); 49 | controllers.put("greeting/", greetingController); 50 | return Collections.unmodifiableMap(controllers); 51 | } 52 | 53 | private static List makeFilters(){ 54 | List filters = new ArrayList(); 55 | filters.add(new LoggingFilter()); 56 | return filters; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/GreetingController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Random; 15 | 16 | import com.mblinn.oo.tinyweb.HttpRequest; 17 | import com.mblinn.oo.tinyweb.TemplateController; 18 | import com.mblinn.oo.tinyweb.View; 19 | 20 | public class GreetingController extends TemplateController { 21 | private Random random; 22 | public GreetingController(View view) { 23 | super(view); 24 | random = new Random(); 25 | } 26 | 27 | @Override 28 | public Map> doRequest(HttpRequest httpRequest) { 29 | Map> helloModel = 30 | new HashMap>(); 31 | helloModel.put("greetings", 32 | generateGreetings(httpRequest.getBody())); 33 | return helloModel; 34 | } 35 | 36 | private List generateGreetings(String namesCommaSeperated) { 37 | String[] names = namesCommaSeperated.split(","); 38 | List greetings = new ArrayList(); 39 | for (String name : names) { 40 | greetings.add(makeGreeting(name)); 41 | } 42 | return greetings; 43 | } 44 | 45 | private String makeGreeting(String name) { 46 | String[] greetings = 47 | { "Hello", "Greetings", "Salutations", "Hola" }; 48 | String greetingPrefix = greetings[random.nextInt(4)]; 49 | return String.format("%s, %s", greetingPrefix, name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/GreetingRenderingStrategy.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.RenderingStrategy; 15 | 16 | public class GreetingRenderingStrategy implements RenderingStrategy { 17 | 18 | @Override 19 | public String renderView(Map> model) { 20 | List greetings = model.get("greetings"); 21 | StringBuffer responseBody = new StringBuffer(); 22 | responseBody.append("

Friendly Greetings:

\n"); 23 | for (String greeting : greetings) { 24 | responseBody.append( 25 | String.format("

%s

\n", greeting)); 26 | 27 | } 28 | return responseBody.toString(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /JavaExamples/src/main/java/com/mblinn/oo/tinyweb/example/LoggingFilter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.tinyweb.example; 10 | 11 | import com.mblinn.oo.tinyweb.Filter; 12 | import com.mblinn.oo.tinyweb.HttpRequest; 13 | 14 | public class LoggingFilter implements Filter { 15 | 16 | @Override 17 | public HttpRequest doFilter(HttpRequest request) { 18 | System.out.println("In Logging Filter - request for path: " 19 | + request.getPath()); 20 | return request; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/fi/PersonExpandedTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.fi; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | 17 | public class PersonExpandedTest { 18 | 19 | ComplicatedNameComparator complicatedNameComparator; 20 | 21 | @Before 22 | public void setup(){ 23 | complicatedNameComparator = new ComplicatedNameComparator(); 24 | } 25 | 26 | @Test 27 | public void complicatedNameComparator_sortsByFirstNameFirst(){ 28 | PersonExpanded p1 = new PersonExpanded("a", "c", "d"); 29 | PersonExpanded p2 = new PersonExpanded("b", "c", "d"); 30 | assertEquals(-1, complicatedNameComparator.compare(p1, p2)); 31 | } 32 | 33 | @Test 34 | public void complicatedNameComparator_sortsByLastNameSecond(){ 35 | PersonExpanded p1 = new PersonExpanded("a", "c", "b"); 36 | PersonExpanded p2 = new PersonExpanded("a", "c", "d"); 37 | assertEquals(-2, complicatedNameComparator.compare(p1, p2)); 38 | } 39 | 40 | @Test 41 | public void complicatedNameComparator_sortsByMiddleNameThird(){ 42 | PersonExpanded p1 = new PersonExpanded("a", "b", "d"); 43 | PersonExpanded p2 = new PersonExpanded("a", "c", "d"); 44 | assertEquals(-1, complicatedNameComparator.compare(p1, p2)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/CommandViewTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | 21 | import com.mblinn.mbfpp.oo.tinyweb.stubs.DummyViewRenderer; 22 | import com.mblinn.mbfpp.oo.tinyweb.stubs.ExceptionalViewRenderer; 23 | import com.mblinn.oo.tinyweb.StrategyView; 24 | import com.mblinn.oo.tinyweb.RenderingException; 25 | import com.mblinn.oo.tinyweb.RenderingStrategy; 26 | 27 | public class CommandViewTest { 28 | 29 | RenderingStrategy dummyViewRenderer; 30 | RenderingStrategy exceptionalViewRenderer; 31 | StrategyView commandView; 32 | Map> model; 33 | 34 | @Before 35 | public void setup(){ 36 | dummyViewRenderer = new DummyViewRenderer(); 37 | exceptionalViewRenderer = new ExceptionalViewRenderer(); 38 | model = new HashMap>(); 39 | List modelValues = new ArrayList(); 40 | modelValues.add("dummyModelValue"); 41 | model.put("dummyModelKey", modelValues); 42 | } 43 | 44 | @Test 45 | public void commandView_rendersUsingViewRenderer(){ 46 | commandView = new StrategyView(dummyViewRenderer); 47 | String body = commandView.render(model); 48 | assertEquals("dummyModelValue", body); 49 | } 50 | 51 | @Test(expected=RenderingException.class) 52 | public void commandView_catchesExceptionsAndWrapsThem(){ 53 | commandView = new StrategyView(exceptionalViewRenderer); 54 | commandView.render(model); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/HttpRequestResponseTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | import org.junit.Test; 14 | 15 | import com.mblinn.oo.tinyweb.HttpRequest; 16 | import com.mblinn.oo.tinyweb.HttpResponse; 17 | 18 | public class HttpRequestResponseTest { 19 | 20 | @Test 21 | public void whenBuildIsCalled_HttpResponseIsCreated() { 22 | HttpResponse httpResponse = HttpResponse.Builder.newBuilder().body("body") 23 | .responseCode(200).build(); 24 | assertEquals("body", httpResponse.getBody()); 25 | assertEquals(Integer.valueOf(200), httpResponse.getResponseCode()); 26 | } 27 | 28 | @Test 29 | public void whenBuildIsCalled_HttpRequestIsCreated() { 30 | HttpRequest httpRequest = HttpRequest.Builder.newBuilder().body("body") 31 | .path("foo").addHeader("foo", "bar").build(); 32 | assertEquals("body", httpRequest.getBody()); 33 | assertEquals("foo", httpRequest.getPath()); 34 | assertEquals("bar", httpRequest.getHeaders().get("foo")); 35 | } 36 | 37 | @Test 38 | public void whenBuilderFromIsCalled_builderStartsWithPassedInRequest() { 39 | HttpRequest httpRequest = HttpRequest.Builder.newBuilder().body("body") 40 | .path("foo").addHeader("foo", "bar").build(); 41 | HttpRequest httpRequest2 = HttpRequest.Builder.builderFrom(httpRequest).addHeader("baz", "quz").build(); 42 | 43 | assertEquals("body", httpRequest2.getBody()); 44 | assertEquals("foo", httpRequest2.getPath()); 45 | assertEquals("bar", httpRequest2.getHeaders().get("foo")); 46 | assertEquals("quz", httpRequest2.getHeaders().get("baz")); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/ITestTinyweb.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | import org.junit.Before; 19 | import org.junit.Test; 20 | 21 | import com.mblinn.mbfpp.oo.tinyweb.stubs.AddDummyHeaderFilter; 22 | import com.mblinn.mbfpp.oo.tinyweb.stubs.DummyController; 23 | import com.mblinn.mbfpp.oo.tinyweb.stubs.DummyViewRenderer; 24 | import com.mblinn.oo.tinyweb.StrategyView; 25 | import com.mblinn.oo.tinyweb.Controller; 26 | import com.mblinn.oo.tinyweb.Filter; 27 | import com.mblinn.oo.tinyweb.HttpRequest; 28 | import com.mblinn.oo.tinyweb.HttpResponse; 29 | import com.mblinn.oo.tinyweb.TinyWeb; 30 | 31 | public class ITestTinyweb { 32 | 33 | TinyWeb tinyWeb; 34 | 35 | @Before 36 | public void setup(){ 37 | DummyViewRenderer viewRenderer = new DummyViewRenderer(); 38 | StrategyView greetingView = new StrategyView(viewRenderer); 39 | DummyController dummyController = new DummyController(greetingView); 40 | 41 | Map controllers = new HashMap(); 42 | controllers.put("dummy/", dummyController); 43 | 44 | List filters = new ArrayList(); 45 | filters.add(new AddDummyHeaderFilter()); 46 | 47 | tinyWeb = new TinyWeb(controllers, filters); 48 | } 49 | 50 | @Test 51 | public void endToEnd(){ 52 | HttpRequest request = HttpRequest.Builder.newBuilder().path("dummy/").build(); 53 | HttpResponse response = tinyWeb.handleRequest(request); 54 | assertEquals(Integer.valueOf(200), response.getResponseCode()); 55 | assertEquals("dummyModelValue", response.getBody()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/TemplateControllerTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.mblinn.mbfpp.oo.tinyweb.stubs.DummyController; 17 | import com.mblinn.mbfpp.oo.tinyweb.stubs.DummyView; 18 | import com.mblinn.mbfpp.oo.tinyweb.stubs.ExceptionalController; 19 | import com.mblinn.mbfpp.oo.tinyweb.stubs.ExceptionalView; 20 | import com.mblinn.oo.tinyweb.HttpRequest; 21 | import com.mblinn.oo.tinyweb.HttpResponse; 22 | 23 | public class TemplateControllerTest { 24 | 25 | DummyController dummyController; 26 | ExceptionalController exceptionalController; 27 | DummyController exceptionalViewController; 28 | DummyView dummyView; 29 | ExceptionalView exceptionalView; 30 | HttpRequest httpRequest; 31 | 32 | @Before 33 | public void setup(){ 34 | dummyView = new DummyView(); 35 | exceptionalView = new ExceptionalView(); 36 | 37 | dummyController = new DummyController(dummyView); 38 | exceptionalController = new ExceptionalController(dummyView); 39 | exceptionalViewController = new DummyController(exceptionalView); 40 | httpRequest = HttpRequest.Builder.newBuilder().build(); 41 | } 42 | 43 | @Test 44 | public void whenRenderIsCalled_viewIsRendered(){ 45 | HttpResponse response = dummyController.handleRequest(httpRequest); 46 | assertEquals("dummyModelValue", response.getBody()); 47 | assertEquals(Integer.valueOf(200), response.getResponseCode()); 48 | } 49 | 50 | @Test 51 | public void whenControllerThrowsException_itIsHandled(){ 52 | HttpResponse response = exceptionalController.handleRequest(httpRequest); 53 | assertEquals("", response.getBody()); 54 | assertEquals(Integer.valueOf(500), response.getResponseCode()); 55 | } 56 | 57 | @Test 58 | public void whenViewRenderingThrowsException_itIsHandled(){ 59 | HttpResponse response = exceptionalViewController.handleRequest(httpRequest); 60 | assertEquals("Exception while rendering.", response.getBody()); 61 | assertEquals(Integer.valueOf(500), response.getResponseCode()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/AddDummyHeaderFilter.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import com.mblinn.oo.tinyweb.Filter; 12 | import com.mblinn.oo.tinyweb.HttpRequest; 13 | 14 | public class AddDummyHeaderFilter implements Filter { 15 | 16 | @Override 17 | public HttpRequest doFilter(HttpRequest request) { 18 | return HttpRequest.Builder.builderFrom(request).addHeader("dummyHeader", "dummyHeaderValue").build(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/DummyController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | import com.mblinn.oo.tinyweb.HttpRequest; 17 | import com.mblinn.oo.tinyweb.TemplateController; 18 | import com.mblinn.oo.tinyweb.View; 19 | 20 | public class DummyController extends TemplateController { 21 | 22 | public DummyController(View view) { 23 | super(view); 24 | } 25 | 26 | @Override 27 | protected Map> doRequest(HttpRequest request) { 28 | Map> dummyMap = new HashMap>(); 29 | List value = new ArrayList(); 30 | value.add("dummyModelValue"); 31 | dummyMap.put("dummyModelKey", value); 32 | return dummyMap; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/DummyView.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.View; 15 | 16 | public class DummyView implements View { 17 | 18 | @Override 19 | public String render(Map> model) { 20 | return model.get("dummyModelKey").get(0); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/DummyViewRenderer.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.RenderingStrategy; 15 | 16 | public class DummyViewRenderer implements RenderingStrategy { 17 | 18 | @Override 19 | public String renderView(Map> model) { 20 | String dummyData = model.get("dummyModelKey").get(0); 21 | return dummyData; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/ExceptionalController.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.HttpRequest; 15 | import com.mblinn.oo.tinyweb.TemplateController; 16 | import com.mblinn.oo.tinyweb.View; 17 | 18 | public class ExceptionalController extends TemplateController { 19 | 20 | public ExceptionalController(View view) { 21 | super(view); 22 | } 23 | 24 | @Override 25 | protected Map> doRequest(HttpRequest request) { 26 | throw new RuntimeException(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/ExceptionalView.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.RenderingException; 15 | import com.mblinn.oo.tinyweb.View; 16 | 17 | public class ExceptionalView implements View { 18 | 19 | @Override 20 | public String render(Map> model) { 21 | throw new RenderingException(new RuntimeException()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/mbfpp/oo/tinyweb/stubs/ExceptionalViewRenderer.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.mbfpp.oo.tinyweb.stubs; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import com.mblinn.oo.tinyweb.RenderingStrategy; 15 | 16 | public class ExceptionalViewRenderer implements RenderingStrategy { 17 | 18 | @Override 19 | public String renderView(Map> model) { 20 | throw new RuntimeException(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/command/CashRegisterTests.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.command; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.mblinn.mbfpp.oo.command.CashRegister; 17 | 18 | public class CashRegisterTests { 19 | 20 | private CashRegister cashRegisterUnderTest; 21 | 22 | @Before 23 | public void setup(){ 24 | cashRegisterUnderTest = new CashRegister(0); 25 | } 26 | 27 | @Test 28 | public void addingMoneyToRegister_addsItToTotal(){ 29 | cashRegisterUnderTest.addCash(100); 30 | assertEquals(Integer.valueOf(100), cashRegisterUnderTest.getTotal()); 31 | cashRegisterUnderTest.addCash(50); 32 | assertEquals(Integer.valueOf(150), cashRegisterUnderTest.getTotal()); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/command/PurchaseInvokerTests.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.command; 10 | 11 | import static org.junit.Assert.assertTrue; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.mblinn.mbfpp.oo.command.PurchaseInvoker; 17 | 18 | public class PurchaseInvokerTests { 19 | 20 | private PurchaseInvoker purchaseInvokerUnderTest; 21 | 22 | private RecordingStubCommand testCommand; 23 | 24 | @Before 25 | public void setUp(){ 26 | purchaseInvokerUnderTest = new PurchaseInvoker(); 27 | testCommand = new RecordingStubCommand(); 28 | } 29 | 30 | @Test 31 | public void executingAPurchase_ShouldExecuteTheUnderlyingCommand(){ 32 | purchaseInvokerUnderTest.executePurchase(testCommand); 33 | assertTrue(testCommand.wasExecuted); 34 | } 35 | 36 | @Test 37 | public void executingAPurchase_ShouldAddTheCommandToHistory(){ 38 | purchaseInvokerUnderTest.executePurchase(testCommand); 39 | assertTrue(testCommand == purchaseInvokerUnderTest.getPurchaseHistory().get(0)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/command/RecordingStubCommand.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.command; 10 | 11 | import com.mblinn.mbfpp.oo.command.Command; 12 | 13 | public class RecordingStubCommand implements Command { 14 | 15 | public boolean wasExecuted = false; 16 | 17 | @Override 18 | public void execute() { 19 | wasExecuted = true; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/iterator/HigherOrderFunctionsTests.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.iterator; 10 | 11 | import static com.mblinn.oo.iterator.HigherOrderFunctions.prependHello; 12 | import static com.mblinn.oo.iterator.HigherOrderFunctions.sumSequence; 13 | import static com.mblinn.oo.iterator.HigherOrderFunctions.vowelsInWord; 14 | import static org.junit.Assert.assertEquals; 15 | 16 | import java.util.ArrayList; 17 | import java.util.HashSet; 18 | import java.util.List; 19 | import java.util.Set; 20 | 21 | import org.junit.Test; 22 | 23 | public class HigherOrderFunctionsTests { 24 | 25 | @Test 26 | public void sumOfEmptySequenceIsZero(){ 27 | List sequence = new ArrayList(); 28 | assertEquals((Integer) 0, sumSequence(sequence)); 29 | } 30 | 31 | @Test 32 | public void sumOfSequenceComputesASequencesSum(){ 33 | List sequence = new ArrayList(); 34 | sequence.add(42); 35 | sequence.add(100); 36 | sequence.add(8); 37 | assertEquals((Integer) 150, sumSequence(sequence)); 38 | } 39 | 40 | @Test 41 | public void sumOfSequenceComputesASequencWithNegatives(){ 42 | List sequence = new ArrayList(); 43 | sequence.add(42); 44 | sequence.add(100); 45 | sequence.add(-42); 46 | assertEquals((Integer) 100, sumSequence(sequence)); 47 | } 48 | 49 | @Test 50 | public void prependHelloPrependsHello(){ 51 | List names = new ArrayList(); 52 | names.add("Michael"); 53 | names.add("Mishu"); 54 | names.add("Joe"); 55 | 56 | List prepended = new ArrayList(); 57 | prepended.add("Hello, Michael"); 58 | prepended.add("Hello, Mishu"); 59 | prepended.add("Hello, Joe"); 60 | 61 | assertEquals(prepended, prependHello(names)); 62 | } 63 | 64 | @Test 65 | public void vowelsInWordReturnsSetOfVowelsInWord(){ 66 | String word = "mishu"; 67 | Set expectedVowels = new HashSet(); 68 | expectedVowels.add('i'); 69 | expectedVowels.add('u'); 70 | 71 | assertEquals(expectedVowels, vowelsInWord(word)); 72 | } 73 | 74 | @Test 75 | public void vowelsInWordWithNoVowelsReturnsEmptySet(){ 76 | String word = "sdf"; 77 | Set expectedVowels = new HashSet(); 78 | 79 | assertEquals(expectedVowels, vowelsInWord(word)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/strategy/DummyValidator.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | public class DummyValidator implements PersonValidator { 12 | 13 | @Override 14 | public boolean validate(Person person) { 15 | return true; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/strategy/FirstNameValidatorTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | import static org.junit.Assert.assertFalse; 12 | import static org.junit.Assert.assertTrue; 13 | 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | 17 | public class FirstNameValidatorTest { 18 | 19 | private FirstNameValidator firstNameValidator; 20 | 21 | @Before 22 | public void setup(){ 23 | firstNameValidator = new FirstNameValidator(); 24 | } 25 | 26 | @Test 27 | public void fullNameValidator_returnsTrueWhenFirstNameIsSet(){ 28 | Person john = new Person("John", "Quincy", "Adams"); 29 | assertTrue(firstNameValidator.validate(john)); 30 | john = new Person("John", null, "Adams"); 31 | assertTrue(firstNameValidator.validate(john)); 32 | john = new Person("John", "Quincy", null); 33 | assertTrue(firstNameValidator.validate(john)); 34 | 35 | } 36 | 37 | @Test 38 | public void fullNameValidator_returnsFalseWhenFirstNameNotSet(){ 39 | Person john = new Person(null, "Quincy", "Adams"); 40 | assertFalse(firstNameValidator.validate(john)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/strategy/FullNameValidatorTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | import static org.junit.Assert.assertFalse; 12 | import static org.junit.Assert.assertTrue; 13 | 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | 17 | public class FullNameValidatorTest { 18 | 19 | FullNameValidator fullNameValidator; 20 | 21 | @Before 22 | public void setup(){ 23 | fullNameValidator = new FullNameValidator(); 24 | } 25 | 26 | @Test 27 | public void fullNameValidator_returnsTrueWhenAllNamesAreSet(){ 28 | Person john = new Person("John", "Quincy", "Adams"); 29 | assertTrue(fullNameValidator.validate(john)); 30 | } 31 | 32 | @Test 33 | public void fullNameValidator_returnsFalseWhenAnyNameNotSet(){ 34 | Person john = new Person("John", null, "Adams"); 35 | assertFalse(fullNameValidator.validate(john)); 36 | john = new Person(null, "Quincy", "Adams"); 37 | assertFalse(fullNameValidator.validate(john)); 38 | john = new Person("John", "Quincy", null); 39 | assertFalse(fullNameValidator.validate(john)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /JavaExamples/src/test/java/com/mblinn/oo/strategy/PersonCollectorTest.java: -------------------------------------------------------------------------------- 1 | /*** 2 | * Excerpted from "Functional Programming Patterns", 3 | * published by The Pragmatic Bookshelf. 4 | * Copyrights apply to this code. It may not be used to create training material, 5 | * courses, books, articles, and the like. Contact us if you are in doubt. 6 | * We make no guarantees that this code is fit for any purpose. 7 | * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information. 8 | ***/ 9 | package com.mblinn.oo.strategy; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | public class PersonCollectorTest { 17 | 18 | PersonCollector personCollector; 19 | 20 | @Before 21 | public void setup(){ 22 | personCollector = new PersonCollector(new DummyValidator()); 23 | } 24 | 25 | @Test 26 | public void personCollector_startsWithEmptyList(){ 27 | assertEquals(0, personCollector.getValidPeople().size()); 28 | } 29 | 30 | @Test 31 | public void personCollector_addsPeopleToList(){ 32 | Person mike = new Person("Mike", "", "Bevilacqua"); 33 | Person rollo = new Person("Rollo", "", "Tomassi"); 34 | 35 | personCollector.addPerson(mike); 36 | personCollector.addPerson(rollo); 37 | 38 | assertEquals(2, personCollector.getValidPeople().size()); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | functional-programming-patterns 2 | =============================== 3 | 4 | - Source Code for Functional Programming Patterns in Scala and Clojure Book 5 | - Unmodified source code can be found here: http://pragprog.com/titles/mbfpp/source_code 6 | -------------------------------------------------------------------------------- /ScalaExamples/build.sbt: -------------------------------------------------------------------------------- 1 | name := "ScalaExamples" 2 | 3 | version := "1.0" 4 | 5 | organization := "com.mblinn" 6 | 7 | libraryDependencies += "com.mblinn" %% "javaexamples" % "1.0" 8 | 9 | libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.3" % "test" 10 | 11 | scalacOptions += "-feature" 12 | -------------------------------------------------------------------------------- /ScalaExamples/project/sbt-idea-shim.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1") 2 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/ccf/Choose.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.ccf 2 | 3 | object Choose { 4 | 5 | def choose[E](num: Int, first: () => E, second: () => E, third: () => E) = 6 | if (num == 1) first() 7 | else if (num == 2) second() 8 | else if (num == 3) third() 9 | 10 | def test[E](expression: E) = expression 11 | 12 | def testTwice[E](expression: E) = { 13 | expression 14 | expression 15 | } 16 | 17 | def printTwice[E](expression: E) { 18 | println(expression) 19 | println(expression) 20 | } 21 | 22 | def testByName[E](expression: => E) = { 23 | expression 24 | expression 25 | } 26 | 27 | def simplerChoose[E](num: Int, first: => E, second: => E, third: => E) = 28 | if (num == 1) first 29 | else if (num == 2) second 30 | else if (num == 3) third 31 | 32 | def timeRun[E](toTime: => E) = { 33 | val start = System.currentTimeMillis 34 | toTime 35 | System.currentTimeMillis - start 36 | } 37 | def avgTime[E](times: Int, toTime: => E) = { 38 | val allTimes = for (_ <- Range(0, times)) yield timeRun(toTime) 39 | allTimes.sum / times 40 | } 41 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/coo/Examples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.coo 2 | 3 | object Examples { 4 | 5 | val name = "michael bevilacqua linn" 6 | val initials = name.split(" ") map (_.toUpperCase) map (_.charAt(0)) mkString 7 | 8 | case class Video(title: String, video_type: String, length: Int) 9 | 10 | val v1 = Video("Pianocat Plays Carnegie Hall", "cat", 300) 11 | val v2 = Video("Paint Drying", "home-improvement", 600) 12 | val v3 = Video("Fuzzy McMittens Live At The Apollo", "cat", 200) 13 | 14 | val videos = Vector(v1, v2, v3) 15 | 16 | def catTime(videos: Vector[Video]) = 17 | videos. 18 | filter((video) => video.video_type == "cat"). 19 | map((video) => video.length). 20 | sum 21 | 22 | val vec1 = Vector(42) 23 | val vec2 = Vector(8) 24 | 25 | for { i1 <- vec1; i2 <- vec2 } yield(i1 + i2) 26 | 27 | val o1 = Some(42) 28 | val o2 = Some(8) 29 | 30 | for { v1 <- o1; v2 <- o2 } yield(v1 + v2) 31 | 32 | val o3: Option[Int] = None 33 | 34 | for { v1 <- o1; v3 <- o3 } yield(v1 + v3) 35 | 36 | case class User(name: String, id: String) 37 | case class Movie(name: String, id: String) 38 | 39 | def getUserById(id: String) = id match { 40 | case "1" => Some(User("Mike", "1")) 41 | case _ => None 42 | } 43 | 44 | def getFavoriteMovieForUser(user: User) = user match { 45 | case User(_, "1") => Some(Movie("Gigli", "101")) 46 | case _ => None 47 | } 48 | 49 | def getVideosForMovie(movie: Movie) = movie match { 50 | case Movie(_, "101") => 51 | Some(Vector( 52 | Video("Interview With Cast", "interview", 480), 53 | Video("Gigli", "feature", 7260))) 54 | case _ => None 55 | } 56 | 57 | def getFavoriteVideos(userId: String) = 58 | for { 59 | user <- getUserById(userId) 60 | favoriteMovie <- getFavoriteMovieForUser(user) 61 | favoriteVideos <- getVideosForMovie(favoriteMovie) 62 | } yield favoriteVideos 63 | 64 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/dsl/Example.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.dsl 2 | import scala.io.Source 3 | import java.lang.Process 4 | import scala.collection.JavaConversions._ 5 | import scala.language.postfixOps 6 | 7 | object Example { 8 | case class CommandResult(status: Int, output: String, error: String) 9 | 10 | class Command(commandParts: List[String]) { 11 | def run() = { 12 | val processBuilder = new ProcessBuilder(commandParts) 13 | val process = processBuilder.start() 14 | val status = process.waitFor() 15 | val outputAsString = 16 | Source.fromInputStream(process.getInputStream()).mkString("") 17 | val errorAsString = 18 | Source.fromInputStream(process.getErrorStream()).mkString("") 19 | CommandResult(status, outputAsString, errorAsString) 20 | } 21 | } 22 | 23 | object Command { 24 | def apply(commandString: String) = new Command(commandString.split("\\s").toList) 25 | } 26 | 27 | implicit class CommandString(commandString: String) { 28 | def run() = Command(commandString).run 29 | } 30 | } 31 | 32 | object ExtendedExample { 33 | case class CommandResult(status: Int, output: String, error: String) 34 | 35 | class Command(commandParts: List[String]) { 36 | def run = { 37 | val processBuilder = new ProcessBuilder(commandParts) 38 | val process = processBuilder.start() 39 | val status = process.waitFor() 40 | val outputAsString = Source.fromInputStream(process.getInputStream()).mkString(""); 41 | val errorAsString = Source.fromInputStream(process.getErrorStream()).mkString(""); 42 | CommandResult(status, outputAsString, errorAsString) 43 | } 44 | 45 | } 46 | 47 | implicit class CommandVector(existingCommands: Vector[String]) { 48 | def run = { 49 | val pipedCommands = existingCommands.mkString(" | ") 50 | Command("/bin/sh", "-c", pipedCommands).run 51 | } 52 | def pipe(nextCommand: String): Vector[String] = { 53 | existingCommands :+ nextCommand 54 | } 55 | } 56 | object Command { 57 | def apply(commandString: String) = new Command(commandString.split("\\s").toList) 58 | def apply(commandParts: String*) = new Command(commandParts.toList) 59 | } 60 | 61 | implicit class CommandString(firstCommandString: String) { 62 | def run = Command(firstCommandString).run 63 | def pipe(secondCommandString: String) = 64 | Vector(firstCommandString, secondCommandString) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/fb/CompositionExamples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | 3 | object ScalaExamples { 4 | 5 | val appendA = (s: String) => s + "a" 6 | val appendB = (s: String) => s + "b" 7 | val appendC = (s: String) => s + "c" 8 | 9 | val appendCBA = appendA compose appendB compose appendC 10 | 11 | case class HttpRequest( 12 | headers: Map[String, String], 13 | payload: String, 14 | principal: Option[String] = None) 15 | 16 | def checkAuthorization(request: HttpRequest) = { 17 | val authHeader = request.headers.get("Authorization") 18 | val mockPrincipal = authHeader match { 19 | case Some(headerValue) => Some("AUser") 20 | case _ => None 21 | } 22 | request.copy(principal = mockPrincipal) 23 | } 24 | 25 | def logFingerprint(request: HttpRequest) = { 26 | val fingerprint = request.headers.getOrElse("X-RequestFingerprint", "") 27 | println("FINGERPRINT=" + fingerprint) 28 | request 29 | } 30 | 31 | def composeFilters(filters: Seq[Function1[HttpRequest, HttpRequest]]) = 32 | filters.reduce { 33 | (allFilters, currentFilter) => allFilters compose currentFilter 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/fb/DiscountBuilder.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | 3 | object DiscountBuilder { 4 | 5 | def discount(percent: Double) = { 6 | if(percent < 0.0 || percent > 100.0) 7 | throw new IllegalArgumentException("Discounts must be between 0.0 and 100.0.") 8 | (originalPrice: Double) => 9 | originalPrice - (originalPrice * percent * 0.01) 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/fb/PartialExamples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | 3 | object PartialExamples { 4 | 5 | def addTwoInts(intOne: Int, intTwo: Int) = intOne + intTwo 6 | 7 | val addFortyTwo = addTwoInts(42, _: Int) 8 | 9 | def taxForState(amount: Double, state: Symbol) = state match { 10 | // Simple tax logic, for example only! 11 | case ('NY) => amount * 0.0645 12 | case ('PA) => amount * 0.045 13 | // Rest of states... 14 | } 15 | val nyTax = taxForState(_: Double, 'NY) 16 | val paTax = taxForState(_: Double, 'PA) 17 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/fb/Selector.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | 3 | import scala.annotation.tailrec 4 | import scala.collection.immutable.Map 5 | import scala.collection.mutable.WrappedArray 6 | 7 | object Selector { 8 | 9 | //TODO: change this all to use functions instead of methods. 10 | 11 | def selector(path: Symbol*): (Map[Symbol, Any] => Option[Any]) = { 12 | 13 | if(path.size <= 0) throw new IllegalArgumentException("path must not be empty") 14 | 15 | @tailrec 16 | def selectorHelper(path: Seq[Symbol], ds: Map[Symbol, Any]): Option[Any] = 17 | if(path.size == 1) { 18 | ds.get(path(0)) 19 | }else{ 20 | val currentPiece = ds.get(path.head) 21 | currentPiece match { 22 | case Some(currentMap: Map[Symbol, Any]) => 23 | selectorHelper(path.tail, currentMap) 24 | case None => None 25 | case _ => None 26 | } 27 | } 28 | 29 | (ds: Map[Symbol, Any]) => selectorHelper(path.toSeq, ds) 30 | } 31 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/ls/LazySequence.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.ls 2 | 3 | import scala.collection.immutable.Stream._ 4 | import scala.util.Random 5 | 6 | object LazySequence { 7 | 8 | val integers = Stream.from(0) 9 | 10 | val generate = new Random() 11 | val randoms = Stream.continually(generate.nextInt) 12 | 13 | def pagedSequence(pageNum: Int): Stream[String] = 14 | getPage(pageNum) match { 15 | case Some(page: String) => page #:: pagedSequence(pageNum + 1) 16 | case None => Stream.Empty 17 | } 18 | 19 | def getPage(page: Int) = 20 | page match { 21 | case 1 => Some("Page1") 22 | case 2 => Some("Page2") 23 | case 3 => Some("Page3") 24 | case _ => None 25 | } 26 | 27 | val holdsHead = { 28 | def pagedSequence(pageNum: Int): Stream[String] = 29 | getPage(pageNum) match { 30 | case Some(page: String) => { 31 | println("Realizing " + page) 32 | page #:: pagedSequence(pageNum + 1) 33 | } 34 | case None => Stream.Empty 35 | } 36 | pagedSequence(1) 37 | } 38 | 39 | def doesntHoldHead = { 40 | def pagedSequence(pageNum: Int): Stream[String] = 41 | getPage(pageNum) match { 42 | case Some(page: String) => { 43 | println("Realizing " + page) 44 | page #:: pagedSequence(pageNum + 1) 45 | } 46 | case None => Stream.Empty 47 | } 48 | pagedSequence(1) 49 | } 50 | 51 | val printHellos = Stream.continually(println("hello")) 52 | 53 | val aStream = "foo" #:: "bar" #:: Stream[String]() 54 | 55 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/memoization/Examples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.memoization 2 | 3 | object Examples { 4 | 5 | def expensiveLookup(id: Int) = { 6 | Thread.sleep(1000) 7 | println(s"Doing expensive lookup for $id") 8 | Map(42 -> "foo", 12 -> "bar", 1 -> "baz").get(id) 9 | } 10 | 11 | def memoizeExpensiveLookup() = { 12 | var cache = Map[Int, Option[String]]() 13 | (id: Int) => 14 | cache.get(id) match { 15 | case Some(result: Option[String]) => result 16 | case None => { 17 | val result = expensiveLookup(id) 18 | cache += id -> result 19 | result 20 | } 21 | } 22 | } 23 | val memoizedExpensiveLookup = memoizeExpensiveLookup 24 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/mfr/Discount.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mfr 2 | 3 | object Discount { 4 | 5 | def calculateDiscount(prices : Seq[Double]) : Double = { 6 | prices filter(price => price >= 20.0) map 7 | (price => price * 0.10) reduce 8 | ((total, price) => total + price) 9 | } 10 | 11 | def calculateDiscountNamedFn(prices : Seq[Double]) : Double = { 12 | def isGreaterThan20(price : Double) = price >= 20.0 13 | def tenPercent(price : Double) = price * 0.10 14 | def sumPrices(total: Double, price : Double) = total + price 15 | 16 | prices filter isGreaterThan20 map tenPercent reduce sumPrices 17 | } 18 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/mr/EvenOdd.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mr 2 | import scala.util.control.TailCalls._ 3 | 4 | object EvenOdd { 5 | 6 | def isOdd(n: Long): Boolean = if (n == 0) false else isEven(n - 1) 7 | 8 | def isEven(n: Long): Boolean = if (n == 0) true else isOdd(n - 1) 9 | 10 | def isOddTrampoline(n: Long): TailRec[Boolean] = 11 | if (n == 0) done(false) else tailcall(isEvenTrampoline(n - 1)) 12 | 13 | def isEvenTrampoline(n: Long): TailRec[Boolean] = 14 | if (n == 0) done(true) else tailcall(isOddTrampoline(n - 1)) 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/mr/Phases.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mr 2 | import scala.util.control.TailCalls._ 3 | 4 | object Phases { 5 | class Transition 6 | case object Ionization extends Transition 7 | case object Deionization extends Transition 8 | case object Vaporization extends Transition 9 | case object Condensation extends Transition 10 | case object Freezing extends Transition 11 | case object Melting extends Transition 12 | case object Sublimation extends Transition 13 | case object Deposition extends Transition 14 | 15 | def plasma(transitions: List[Transition]): TailRec[Boolean] = transitions match { 16 | case Nil => done(true) 17 | case Deionization :: restTransitions => tailcall(vapor(restTransitions)) 18 | case _ => done(false) 19 | } 20 | def vapor(transitions: List[Transition]): TailRec[Boolean] = transitions match { 21 | case Nil => done(true) 22 | case Condensation :: restTransitions => tailcall(liquid(restTransitions)) 23 | case Deposition :: restTransitions => tailcall(solid(restTransitions)) 24 | case Ionization :: restTransitions => tailcall(plasma(restTransitions)) 25 | case _ => done(false) 26 | } 27 | 28 | def liquid(transitions: List[Transition]): TailRec[Boolean] = transitions match { 29 | case Nil => done(true) 30 | case Vaporization :: restTransitions => tailcall(vapor(restTransitions)) 31 | case Freezing :: restTransitions => tailcall(solid(restTransitions)) 32 | case _ => done(false) 33 | } 34 | 35 | def solid(transitions: List[Transition]): TailRec[Boolean] = transitions match { 36 | case Nil => done(true) 37 | case Melting :: restTransitions => tailcall(liquid(restTransitions)) 38 | case Sublimation :: restTransitions => tailcall(vapor(restTransitions)) 39 | case _ => done(false) 40 | } 41 | 42 | val validSequence = List(Melting, Vaporization, Ionization, Deionization) 43 | 44 | val invalidSequence = List(Vaporization, Freezing) 45 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/functional/tr/Names.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.tr 2 | import scala.annotation.tailrec 3 | 4 | object Names { 5 | 6 | case class Person(firstNames: String, lastNames: String) 7 | 8 | /* 9 | val makePeople = (firstNames: Seq[String], lastNames: Seq[String]) => { 10 | @tailrec 11 | lazy val helper: (Seq[String], Seq[String], Vector[Person]) => Seq[Person] = 12 | (firstNames: Seq[String], lastNames: Seq[String], people: Vector[Person]) => { 13 | if (firstNames.isEmpty) 14 | people 15 | else { 16 | val newPerson = Person(firstNames.head, lastNames.head) 17 | helper(firstNames.tail, lastNames.tail, people :+ newPerson) 18 | } 19 | } 20 | 21 | helper(firstNames, lastNames, Vector[Person]()) 22 | }*/ 23 | 24 | def makePeople(firstNames: Seq[String], lastNames: Seq[String]) = { 25 | @tailrec 26 | def helper(firstNames: Seq[String], lastNames: Seq[String], 27 | people: Vector[Person]): Seq[Person] = 28 | if (firstNames.isEmpty) 29 | people 30 | else { 31 | val newPerson = Person(firstNames.head, lastNames.head) 32 | helper(firstNames.tail, lastNames.tail, people :+ newPerson) 33 | } 34 | helper(firstNames, lastNames, Vector[Person]()) 35 | } 36 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/command/register/Register.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.command.register 2 | 3 | class CashRegister(var total: Int) { 4 | def addCash(toAdd: Int) { 5 | total += toAdd 6 | } 7 | } 8 | 9 | object Register { 10 | def makePurchase(register: CashRegister, amount: Int) = { 11 | () => { 12 | println("Purchase in amount: " + amount) 13 | register.addCash(amount) 14 | } 15 | } 16 | 17 | var purchases: Vector[() => Unit] = Vector() 18 | def executePurchase(purchase: () => Unit) = { 19 | purchases = purchases :+ purchase 20 | purchase() 21 | } 22 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/decorator/Examples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.decorator 2 | 3 | object Examples { 4 | 5 | def add(a: Int, b: Int) = a + b 6 | def subtract(a: Int, b: Int) = a - b 7 | def multiply(a: Int, b: Int) = a * b 8 | def divide(a: Int, b: Int) = a / b 9 | 10 | def makeLogger(calcFn: (Int, Int) => Int) = 11 | (a: Int, b: Int) => { 12 | val result = calcFn(a, b) 13 | println("Result is: " + result) 14 | result 15 | } 16 | 17 | val loggingAdd = makeLogger(add) 18 | val loggingSubtract = makeLogger(subtract) 19 | val loggingMultiply = makeLogger(multiply) 20 | val loggingDivide = makeLogger(divide) 21 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/fi/PersonExample.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.fi.person 2 | 3 | object PersonExample { 4 | (int1: Int, int2: Int) => int1 + int2 5 | 6 | case class Person(firstName: String, lastName: String) 7 | 8 | val p1 = Person("Michael", "Bevilacqua") 9 | val p2 = Person("Pedro", "Vasquez") 10 | val p3 = Person("Robert", "Aarons") 11 | 12 | val people = Vector(p3, p2, p1) 13 | 14 | people.sortWith((p1, p2) => p1.firstName < p2.firstName) 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/fi/PersonExpanded.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.fi.personexpanded 2 | 3 | object PersonExample { 4 | case class Person(firstName: String, middleName: String, lastName: String) 5 | val p1 = Person("Aaron", "Jeffrey", "Smith") 6 | val p2 = Person("Aaron", "Bailey", "Zanthar") 7 | val p3 = Person("Brian", "Adams", "Smith") 8 | val people = Vector(p1, p2, p3) 9 | 10 | def complicatedSort(p1: Person, p2: Person) = 11 | if (p1.firstName != p2.firstName) 12 | p1.firstName < p2.firstName 13 | else if (p1.lastName != p2.lastName) 14 | p1.lastName < p2.lastName 15 | else 16 | p1.middleName < p2.middleName 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/fi/personexpanded/ClosureExample.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.fi.personexpanded 2 | 3 | object ClosureExample { 4 | 5 | case class Person(firstName: String, middleName: String, lastName: String) 6 | 7 | def makeComposedComparison(comparisons: (Person, Person) => Int*) = 8 | (p1: Person, p2: Person) => 9 | comparisons.map(cmp => cmp(p1, p2)).find(_ != 0).getOrElse(0) 10 | 11 | def firstNameComparison(p1: Person, p2: Person) = 12 | p1.firstName.compareTo(p2.firstName) 13 | 14 | def lastNameComparison(p1: Person, p2: Person) = 15 | p1.lastName.compareTo(p2.lastName) 16 | 17 | val firstAndLastNameComparison = makeComposedComparison( 18 | firstNameComparison, lastNameComparison 19 | ) 20 | 21 | val p1 = Person("John", "", "Adams") 22 | val p2 = Person("John", "Quincy", "Adams") 23 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/iterator/HigherOrderFunctions.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.iterator 2 | 3 | object HigherOrderFunctions { 4 | 5 | def sumSequence(sequence : Seq[Int]) = 6 | if(sequence.isEmpty) 0 else sequence.reduce((acc, curr) => acc + curr) 7 | 8 | def prependHello(names : Seq[String]) = 9 | names.map((name) => "Hello, " + name) 10 | 11 | val isVowel = Set('a', 'e', 'i', 'o', 'u') 12 | def vowelsInWord(word: String) = word.filter(isVowel).toSet 13 | 14 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/iterator/TheLambdaBarAndGrille.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.iterator 2 | 3 | import com.mblinn.oo.iterator.Address; 4 | 5 | object TheLambdaBarAndGrille { 6 | 7 | case class Person(name: String, address: Address) 8 | case class Address(zip: Int) 9 | def generateGreetings(people: Seq[Person]) = 10 | for (Person(name, address) <- people if isCloseZip(address.zip)) 11 | yield "Hello, %s, and welcome to the Lambda Bar And Grille!".format(name) 12 | def isCloseZip(zipCode: Int) = zipCode == 19123 || zipCode == 19103 13 | 14 | def printGreetings(people: Seq[Person]) = 15 | for (Person(name, address) <- people if isCloseZip(address.zip)) 16 | println("Hello, %s, and welcome to the Lambda Bar And Grille!".format(name)) 17 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/javabean/Person.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.javabean 2 | 3 | class Person( 4 | val firstName: String, 5 | val middleName: String, 6 | val lastName: String) 7 | 8 | class PersonWithDefault( 9 | val firstName: String, 10 | val middleName: String = "", 11 | val lastName: String) 12 | 13 | case class PersonCaseClass( 14 | firstName: String, 15 | middleName: String = "", 16 | lastName: String) 17 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/nullobject/Examples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.nullobject 2 | 3 | object Examples { 4 | 5 | case class Person(firstName: String="John", lastName: String="Doe") 6 | val nullPerson = Person() 7 | 8 | def fetchPerson(people: Map[Int, Person], id: Int) = 9 | people.getOrElse(id, nullPerson) 10 | 11 | val joe = Person("Joe", "Smith") 12 | val jack = Person("Jack", "Brown") 13 | val somePeople = Map(1 -> joe, 2 -> jack) 14 | 15 | def vecFoo = Vector("foo") 16 | def someFoo = Some("foo") 17 | def someBar = Some("bar") 18 | def aNone = None 19 | 20 | def buildPerson(firstNameOption: Option[String], lastNameOption: Option[String]) = 21 | (for( 22 | firstName <- firstNameOption; 23 | lastName <- lastNameOption) 24 | yield Person(firstName, lastName)).getOrElse(Person("John", "Doe")) 25 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/strategy/PeopleExample.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.strategy 2 | 3 | object PeopleExample { 4 | case class Person( 5 | firstName: Option[String], 6 | middleName: Option[String], 7 | lastName: Option[String]) 8 | 9 | def isFirstNameValid(person: Person) = person.firstName.isDefined 10 | 11 | def isFullNameValid(person: Person) = person match { 12 | case Person(firstName, middleName, lastName) => 13 | firstName.isDefined && middleName.isDefined && lastName.isDefined 14 | } 15 | 16 | def personCollector(isValid: (Person) => Boolean) = { 17 | var validPeople = Vector[Person]() 18 | (person: Person) => { 19 | if(isValid(person)) validPeople = validPeople :+ person 20 | validPeople 21 | } 22 | } 23 | 24 | val p1 = Person(Some("John"), Some("Quincy"), Some("Adams")) 25 | val p2 = Person(Some("Mike"), None, Some("Linn")) 26 | val p3 = Person(None, None, None) 27 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/example/Example.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.example 2 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.Controller 3 | import scala.util.Random 4 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.HttpRequest 5 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.View 6 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.FunctionView 7 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.FunctionController 8 | import com.mblinn.mbfpp.oo.tinyweb.stepfour.TinyWeb 9 | 10 | object Example { 11 | 12 | def greetingViewRenderer(model: Map[String, List[String]]) = 13 | "

Friendly Greetings:%s".format( 14 | model 15 | getOrElse("greetings", List[String]()) 16 | map(renderGreeting) 17 | mkString ", ") 18 | 19 | private def renderGreeting(greeting: String) = 20 | "

%s

".format(greeting) 21 | 22 | def greetingView = new FunctionView(greetingViewRenderer) 23 | 24 | def handleGreetingRequest(request: HttpRequest) = 25 | Map("greetings" -> request.body.split(",").toList.map(makeGreeting)) 26 | 27 | private def random = new Random() 28 | private def greetings = Vector("Hello", "Greetings", "Salutations", "Hola") 29 | private def makeGreeting(name: String) = 30 | "%s, %s".format(greetings(random.nextInt(greetings.size)), name) 31 | 32 | def greetingController = new FunctionController(greetingView, handleGreetingRequest) 33 | 34 | private def loggingFilter(request: HttpRequest) = { 35 | println("In Logging Filter - request for path: %s".format(request.path)) 36 | request 37 | } 38 | 39 | def tinyweb = new TinyWeb( 40 | Map("/greeting" -> greetingController), 41 | List(loggingFilter)) 42 | def testHttpRequest = HttpRequest( 43 | body="Mike,Joe,John,Steve", 44 | path="/greeting") 45 | 46 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepfour/Controller.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepfour 2 | import com.mblinn.oo.tinyweb.ControllerException 3 | import com.mblinn.oo.tinyweb.RenderingException 4 | 5 | trait Controller { 6 | def handleRequest(httpRequest: HttpRequest): HttpResponse 7 | } 8 | 9 | class FunctionController(view: View, doRequest: (HttpRequest) => 10 | Map[String, List[String]] ) extends Controller { 11 | 12 | def handleRequest(request: HttpRequest): HttpResponse = 13 | try { 14 | val model = doRequest(request) 15 | val responseBody = view.render(model) 16 | HttpResponse(responseBody, 200) 17 | } catch { 18 | case e: ControllerException => 19 | HttpResponse("", e.getStatusCode) 20 | case e: RenderingException => 21 | HttpResponse("Exception while rendering.", 500) 22 | case e: Exception => 23 | HttpResponse("", 500) 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepfour/HttpData.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepfour 2 | 3 | case class HttpRequest(headers: Map[String, String] = Map(), body: String, path: String) 4 | case class HttpResponse(body: String, responseCode: Integer) 5 | 6 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepfour/Tinyweb.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepfour 2 | class TinyWeb(controllers: Map[String, Controller], 3 | filters: List[(HttpRequest) => HttpRequest]) { 4 | 5 | def handleRequest(httpRequest: HttpRequest): Option[HttpResponse] = { 6 | val composedFilter = filters.reverse.reduceLeft( 7 | (composed, next) => composed compose next) 8 | val filteredRequest = composedFilter(httpRequest) 9 | val controllerOption = controllers.get(filteredRequest.path) 10 | controllerOption map { controller => controller.handleRequest(filteredRequest) } 11 | } 12 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepfour/View.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepfour 2 | import com.mblinn.oo.tinyweb.RenderingException 3 | 4 | trait View { 5 | def render(model: Map[String, List[String]]): String 6 | } 7 | 8 | class FunctionView(viewRenderer: (Map[String, List[String]]) => String) extends View { 9 | def render(model: Map[String, List[String]]) = 10 | try 11 | viewRenderer(model) 12 | catch { 13 | case e: Exception => throw new RenderingException(e) 14 | } 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepone/View.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepone 2 | import com.mblinn.oo.tinyweb.RenderingException 3 | 4 | trait View { 5 | def render(model: Map[String, List[String]]): String 6 | } 7 | class FunctionView(viewRenderer: (Map[String, List[String]]) => String) 8 | extends View { 9 | def render(model: Map[String, List[String]]) = 10 | try 11 | viewRenderer(model) 12 | catch { 13 | case e: Exception => throw new RenderingException(e) 14 | } 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepthree/Controller.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepthree 2 | import com.mblinn.oo.tinyweb.ControllerException 3 | import com.mblinn.oo.tinyweb.RenderingException 4 | 5 | trait Controller { 6 | def handleRequest(httpRequest: HttpRequest): HttpResponse 7 | } 8 | class FunctionController(view: View, doRequest: (HttpRequest) => 9 | Map[String, List[String]] ) extends Controller { 10 | def handleRequest(request: HttpRequest): HttpResponse = 11 | try { 12 | val model = doRequest(request) 13 | val responseBody = view.render(model) 14 | HttpResponse(responseBody, 200) 15 | } catch { 16 | case e: ControllerException => 17 | HttpResponse("", e.getStatusCode) 18 | case e: RenderingException => 19 | HttpResponse("Exception while rendering.", 500) 20 | case e: Exception => 21 | HttpResponse("", 500) 22 | } 23 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepthree/HttpData.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepthree 2 | 3 | case class HttpRequest(headers: Map[String, String], body: String, path: String) 4 | case class HttpResponse(body: String, responseCode: Integer) 5 | 6 | -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/stepthree/View.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.stepthree 2 | import com.mblinn.oo.tinyweb.RenderingException 3 | 4 | trait View { 5 | def render(model: Map[String, List[String]]): String 6 | } 7 | 8 | class FunctionView(viewRenderer: (Map[String, List[String]]) => String) extends View { 9 | def render(model: Map[String, List[String]]) = 10 | try 11 | viewRenderer(model) 12 | catch { 13 | case e: Exception => throw new RenderingException(e) 14 | } 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/steptwo/Controller.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.steptwo 2 | 3 | import com.mblinn.oo.tinyweb.HttpRequest 4 | import com.mblinn.oo.tinyweb.HttpResponse 5 | import com.mblinn.oo.tinyweb.ControllerException 6 | import com.mblinn.oo.tinyweb.RenderingException 7 | 8 | trait Controller { 9 | def handleRequest(httpRequest: HttpRequest): HttpResponse 10 | } 11 | 12 | class FunctionController(view: View, doRequest: (HttpRequest) => 13 | Map[String, List[String]] ) extends Controller { 14 | 15 | def handleRequest(request: HttpRequest): HttpResponse = { 16 | var responseCode = 200; 17 | var responseBody = ""; 18 | 19 | try { 20 | val model = doRequest(request) 21 | responseBody = view.render(model) 22 | } catch { 23 | case e: ControllerException => 24 | responseCode = e.getStatusCode() 25 | case e: RenderingException => 26 | responseCode = 500 27 | responseBody = "Exception while rendering." 28 | case e: Exception => 29 | responseCode = 500 30 | } 31 | 32 | HttpResponse.Builder.newBuilder() 33 | .body(responseBody).responseCode(responseCode).build() 34 | } 35 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tinyweb/steptwo/View.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tinyweb.steptwo 2 | import com.mblinn.oo.tinyweb.RenderingException 3 | 4 | trait View { 5 | def render(model: Map[String, List[String]]): String 6 | } 7 | 8 | class FunctionView(viewRenderer: (Map[String, List[String]]) => String) extends View { 9 | def render(model: Map[String, List[String]]) = 10 | try 11 | viewRenderer(model) 12 | catch { 13 | case e: Exception => throw new RenderingException(e) 14 | } 15 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/tm/GradeReporter.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.tm 2 | import scala.collection.immutable.SortedMap 3 | import scala.collection.immutable.TreeMap 4 | 5 | object GradeReporter { 6 | 7 | def makeGradeReporter( 8 | numToLetter: (Double) => String, 9 | printGradeReport: (Seq[String]) => Unit) = (grades: Seq[Double]) => { 10 | printGradeReport(grades.map(numToLetter)) 11 | } 12 | 13 | def fullGradeConverter(grade: Double) = 14 | if(grade <= 5.0 && grade > 4.0) "A" 15 | else if(grade <= 4.0 && grade > 3.0) "B" 16 | else if(grade <= 3.0 && grade > 2.0) "C" 17 | else if(grade <= 2.0 && grade > 0.0) "D" 18 | else if(grade == 0.0) "F" 19 | else "N/A" 20 | 21 | def printHistogram(grades: Seq[String]) = { 22 | val grouped = grades.groupBy(identity) 23 | val counts = grouped.map((kv) => (kv._1, kv._2.size)).toSeq.sorted 24 | for(count <- counts) { 25 | val stars = "*" * count._2 26 | println("%s: %s".format(count._1, stars)) 27 | } 28 | } 29 | 30 | val sampleGrades = Vector(5.0, 4.0, 4.4, 2.2, 3.3, 3.5) 31 | 32 | val fullGradeReporter = makeGradeReporter(fullGradeConverter, printHistogram) 33 | 34 | def plusMinusGradeConverter(grade: Double) = 35 | if(grade <= 5.0 && grade > 4.7) "A" 36 | else if(grade <= 4.7 && grade > 4.3) "A-" 37 | else if(grade <= 4.3 && grade > 4.0) "B+" 38 | else if(grade <= 4.0 && grade > 3.7) "B" 39 | else if(grade <= 3.7 && grade > 3.3) "B-" 40 | else if(grade <= 3.3 && grade > 3.0) "C+" 41 | else if(grade <= 3.0 && grade > 2.7) "C" 42 | else if(grade <= 2.7 && grade > 2.3) "C-" 43 | else if(grade <= 2.3 && grade > 0.0) "D" 44 | else if(grade == 0.0) "F" 45 | else "N/A" 46 | 47 | def printAllGrades(grades: Seq[String]) = 48 | for(grade <- grades) println("Grade is: " + grade) 49 | 50 | val plusMinusGradeReporter = 51 | makeGradeReporter(plusMinusGradeConverter, printAllGrades) 52 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/visitor/Examples.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.visitor 2 | 3 | object Examples { 4 | trait Person { 5 | def fullName: String 6 | def firstName: String 7 | def lastName: String 8 | def houseNum: Int 9 | def street: String 10 | } 11 | 12 | class SimplePerson(val firstName: String, val lastName: String, 13 | val houseNum: Int, val street: String) extends Person { 14 | def fullName = firstName + " " + lastName 15 | } 16 | 17 | class ComplexPerson(name: Name, address: Address) extends Person { 18 | def fullName = name.firstName + " " + name.lastName 19 | 20 | def firstName = name.firstName 21 | def lastName = name.lastName 22 | def houseNum = address.houseNum 23 | def street = address.street 24 | } 25 | class Address(val houseNum: Int, val street: String) 26 | class Name(val firstName: String, val lastName: String) 27 | 28 | implicit class ExtendedPerson(person: Person) { 29 | def fullAddress = person.houseNum + " " + person.street 30 | } 31 | } -------------------------------------------------------------------------------- /ScalaExamples/src/main/scala/com/mblinn/mbfpp/oo/visitor/Shapes.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.visitor 2 | 3 | 4 | trait PerimeterShapes { 5 | trait Shape { 6 | def perimeter: Double 7 | } 8 | 9 | class Circle(radius: Double) extends Shape { 10 | def perimeter = 2 * Math.PI * radius 11 | } 12 | 13 | class Rectangle(width: Double, height: Double) extends Shape { 14 | def perimeter = 2 * width + 2 * height 15 | } 16 | } 17 | 18 | object FirstShapeExample extends PerimeterShapes { 19 | val aCircle = new Circle(4); 20 | val aRectangle = new Rectangle(2, 2); 21 | } 22 | 23 | trait AreaShapes extends PerimeterShapes { 24 | trait Shape extends super.Shape { 25 | def area: Double 26 | } 27 | 28 | class Circle(radius: Double) extends super.Circle(radius) with Shape { 29 | def area = Math.PI * radius * radius 30 | } 31 | 32 | class Rectangle(width: Double, height: Double) 33 | extends super.Rectangle(width, height) with Shape { 34 | def area = width * height 35 | } 36 | } 37 | 38 | object SecondShapeExample extends AreaShapes { 39 | val someShapes = Vector(new Circle(4), new Rectangle(2, 2)); 40 | } 41 | 42 | trait MorePerimeterShapes extends PerimeterShapes { 43 | class Square(side: Double) extends Shape { 44 | def perimeter = 4 * side; 45 | } 46 | } 47 | 48 | trait MoreAreaShapes extends AreaShapes with MorePerimeterShapes { 49 | class Square(side: Double) extends super.Square(side) with Shape { 50 | def area = side * side 51 | } 52 | } 53 | 54 | object ThirdShapeExample extends MoreAreaShapes { 55 | val someMoreShapes = Vector(new Circle(4), new Rectangle(2, 2), new Square(4)); 56 | } 57 | -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/ccf/ChooseSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.ccf 2 | import org.junit.runner.RunWith 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.scalatest.junit.JUnitRunner 6 | 7 | import com.mblinn.mbfpp.functional.ccf.Choose._ 8 | 9 | @RunWith(classOf[JUnitRunner]) 10 | class ChooseSpec extends FunSpec with ShouldMatchers { 11 | 12 | describe("the choose examples") { 13 | 14 | it("should choose the appropriate function") { 15 | val f1 = () => "f1" 16 | val f2 = () => "f2" 17 | val f3 = () => "f3" 18 | 19 | choose(1, f1, f2, f3) should equal("f1") 20 | choose(2, f1, f2, f3) should equal("f2") 21 | choose(3, f1, f2, f3) should equal("f3") 22 | } 23 | 24 | it("should choose the appropriate expression"){ 25 | val e1 = "f1" 26 | val e2 = "f2" 27 | val e3 = "f3" 28 | 29 | simplerChoose(1, e1, e2, e3) should equal("f1") 30 | simplerChoose(2, e1, e2, e3) should equal("f2") 31 | simplerChoose(3, e1, e2, e3) should equal("f3") 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/fb/DiscountBuilder.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | import org.scalatest.junit.JUnitRunner 3 | import org.scalatest.FunSpec 4 | import com.mblinn.mbfpp.functional.fb.DiscountBuilder._ 5 | import org.junit.runner.RunWith 6 | import org.scalatest.matchers.ShouldMatchers 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class DiscountBuilderSpec extends FunSpec with ShouldMatchers { 10 | 11 | describe("A Discount Calculator Builder") { 12 | 13 | it("should return a function that applies a zero percent discount") { 14 | discount(0)(100) should equal(100) 15 | } 16 | 17 | it("should return a function that applies a 100 percent discount") { 18 | discount(100)(100) should equal(0) 19 | } 20 | 21 | it("should return a function that applies discounts between 1 and 99") { 22 | for(percentage <- Range(1, 100)) { 23 | discount(percentage)(100) should equal(100 - (percentage * 100 * 0.01)) 24 | } 25 | } 26 | 27 | it("should only allow discounts in the range between 0 and 100") { 28 | evaluating { discount(-1) } should produce [IllegalArgumentException] 29 | evaluating { discount(101) } should produce [IllegalArgumentException] 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/fb/Selector.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.fb 2 | import org.scalatest.junit.JUnitRunner 3 | import org.scalatest.FunSpec 4 | import org.junit.runner.RunWith 5 | import org.scalatest.matchers.ShouldMatchers 6 | import com.mblinn.mbfpp.functional.fb.Selector._ 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class SelectorSpec extends FunSpec with ShouldMatchers { 10 | 11 | describe("A Selector Builder") { 12 | it("should create a selector capable of extracting a key one layer deep") { 13 | val ds = Map('foo -> "foo") 14 | selector('foo)(ds) should equal(Some("foo")) 15 | } 16 | 17 | it("should create a selector capable of extracing a key several layers deep") { 18 | val ds = Map('foo -> Map('bar -> Map('baz -> "baz"))) 19 | selector('foo, 'bar, 'baz)(ds) should equal(Some("baz")) 20 | } 21 | 22 | it("should create a selector that returns None if it does not match") { 23 | val ds = Map('foo -> Map('bar -> Map('baz -> "baz"))) 24 | selector('foo, 'quz)(ds) should equal(None) 25 | } 26 | 27 | it("should create a selector that returns None if an intermedia part of the datastructure is not Map[Symbol, Any]") { 28 | val ds = Map('foo -> Vector('bar)) 29 | selector('foo, 'bar)(ds) should equal(None) 30 | } 31 | 32 | it("should not allow an empty path") { 33 | evaluating { selector() } should produce[IllegalArgumentException] 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/mfr/DiscountSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mfr 2 | import org.scalatest.junit.JUnitRunner 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import com.mblinn.mbfpp.functional.mfr.Discount._ 6 | import org.scalatest.junit.JUnitRunner 7 | import org.junit.runner.RunWith 8 | 9 | @RunWith(classOf[JUnitRunner]) 10 | class DiscountSpec extends FunSpec with ShouldMatchers { 11 | 12 | describe("The discount functions.") { 13 | it("should throw an exception on an empty sequence") { 14 | evaluating { calculateDiscount(Vector()) } should produce[UnsupportedOperationException] 15 | } 16 | 17 | it("should calculate a discount of 10 percent on items 20 dollars or greater.") { 18 | calculateDiscount(Vector(20.0, 4.5, 50.0, 15.75, 30.0, 3.50)) should equal(10) 19 | calculateDiscount(Vector(4.5, 15.75, 3.50)) should equal(0) 20 | } 21 | 22 | it("calculate discount and calculate discount named fn should work the same.") { 23 | calculateDiscount(Vector(20.0, 4.5, 50.0, 15.75, 30.0, 3.50)) should equal(calculateDiscountNamedFn(Vector(20.0, 4.5, 50.0, 15.75, 30.0, 3.50))) 24 | calculateDiscount(Vector(4.5, 15.75, 3.50)) should equal(calculateDiscountNamedFn(Vector(4.5, 15.75, 3.50))) 25 | } 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/mr/EvenOddSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mr 2 | import org.junit.runner.RunWith 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.scalatest.junit.JUnitRunner 6 | import com.mblinn.mbfpp.functional.mr.EvenOdd._ 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class EvenOddSpec extends FunSpec with ShouldMatchers { 10 | 11 | describe("The even and odd functions should determine even and odd.") { 12 | it("should calculate odd and even correctly") { 13 | isOdd(100) should equal(false) 14 | isEven(100) should equal(true) 15 | isOdd(101) should equal(true) 16 | isEven(101) should equal(false) 17 | isOddTrampoline(100).result should equal(false) 18 | isEvenTrampoline(100).result should equal(true) 19 | isOddTrampoline(101).result should equal(true) 20 | isEvenTrampoline(101).result should equal(false) 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/mr/PhasesSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.mr 2 | import com.mblinn.mbfpp.functional.mr.Phases._ 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.junit.runner.RunWith 6 | import org.scalatest.junit.JUnitRunner 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class PhasesSpec extends FunSpec with ShouldMatchers { 10 | describe("A phases state machine"){ 11 | it("should treat liquid-solid-liquid-vapor-plasma-liquid as valid"){ 12 | val sequence = List(Freezing, Melting, Vaporization, Ionization, Deionization) 13 | liquid(sequence).result should equal(true) 14 | } 15 | it("should treat liquid-plasma as invalid"){ 16 | liquid(List(Ionization)).result should equal(false) 17 | } 18 | it("should treat the empty sequence as valid"){ 19 | liquid(List()).result should equal(true) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/strategy/PeopleExampleSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.strategy 2 | import org.scalatest.matchers.ShouldMatchers 3 | import org.scalatest.FunSpec 4 | import org.junit.runner.RunWith 5 | import org.scalatest.junit.JUnitRunner 6 | import com.mblinn.mbfpp.oo.strategy.PeopleExample._ 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class PeopleExampleSpec extends FunSpec with ShouldMatchers { 10 | 11 | describe("isFirstNameValid"){ 12 | it("should consider any person with a first name valid"){ 13 | isFirstNameValid(Person(Some("Mike"), None, None)) should equal (true) 14 | isFirstNameValid(Person(Some("Mike"), Some("Peter"), None)) should equal (true) 15 | isFirstNameValid(Person(Some("Mike"), Some("Peter"), Some("Linn"))) should equal (true) 16 | } 17 | 18 | it("should consider any person without a first name invalid"){ 19 | isFirstNameValid(Person(None, None, None)) should equal (false) 20 | isFirstNameValid(Person(None, Some("Peter"), None)) should equal (false) 21 | isFirstNameValid(Person(None, Some("Peter"), Some("Linn"))) should equal (false) 22 | } 23 | } 24 | 25 | describe("isFullNameValid"){ 26 | it("considers a person valid only if it has all three names"){ 27 | isFullNameValid(Person(None, None, None)) should equal (false) 28 | isFullNameValid(Person(Some("Mike"), None, None)) should equal (false) 29 | isFullNameValid(Person(Some("Mike"), Some("Peter"), None)) should equal (false) 30 | isFullNameValid(Person(Some("Mike"), Some("Peter"), Some("Linn"))) should equal (true) 31 | } 32 | } 33 | 34 | describe("personCollector"){ 35 | it("collects valid people and returns the set of valid people its seen so far"){ 36 | val collectPerson = personCollector((person: Person) => true) 37 | val p1 = Person(Some("fn1"), Some("mn1"), Some("ln1")) 38 | val p2 = Person(Some("fn2"), Some("mn2"), Some("ln2")) 39 | var expected = Vector(p1) 40 | collectPerson(p1) should equal (expected) 41 | expected = expected :+ p2 42 | collectPerson(p2) should equal(expected) 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/functional/tr/NamesSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.functional.tr 2 | import org.junit.runner.RunWith 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.scalatest.junit.JUnitRunner 6 | import com.mblinn.mbfpp.functional.tr.Names._ 7 | 8 | @RunWith(classOf[JUnitRunner]) 9 | class NamesSpec extends FunSpec with ShouldMatchers { 10 | 11 | describe("makePeople"){ 12 | it("should make people from two lists of names."){ 13 | makePeople(List("firstone", "firsttwo"), List("lastone", "lasttwo")) should equal( 14 | List(Person("firstone", "lastone"), Person("firsttwo", "lasttwo"))) 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/oo/fi/PersonExampleSpec.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.fi 2 | 3 | //import com.mblinn.mbfpp.oo.fi.person.PersonExample.Person 4 | import org.junit.runner.RunWith 5 | import org.scalatest.matchers.ShouldMatchers 6 | import org.scalatest.FunSpec 7 | import org.scalatest.junit.JUnitRunner 8 | /* 9 | @RunWith(classOf[JUnitRunner]) 10 | class PersonExampleSpec extends FunSpec with ShouldMatchers { 11 | describe("person sorting") { 12 | it("should return an empty sequence when passed an empty sequence.") { 13 | val people = Vector[Person]() 14 | people.sortWith( 15 | (p1: Person, p2: Person) => p1.firstName < p2.firstName) should equal(Vector[Person]()) 16 | 17 | } 18 | it("should sort people by first name.") { 19 | val p1 = Person("Michael", "Bevilacqua") 20 | val p2 = Person("Pedro", "Vasquez") 21 | val p3 = Person("Robert", "Aarons") 22 | val people = Vector(p3, p2, p1) 23 | val sortedPeople = Vector(p1, p2, p3) 24 | 25 | people.sortWith( 26 | (p1: Person, p2: Person) => p1.firstName < p2.firstName) should equal(sortedPeople) 27 | } 28 | } 29 | }*/ -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/oo/iterator/HigherOrderFunctions.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.iterator 2 | import org.junit.runner.RunWith 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.scalatest.junit.JUnitRunner 6 | 7 | import com.mblinn.mbfpp.oo.iterator.HigherOrderFunctions._ 8 | 9 | @RunWith(classOf[JUnitRunner]) 10 | class HigherOrderFunctionSpecs extends FunSpec with ShouldMatchers { 11 | describe("sumSequence"){ 12 | it("should sum a sequence"){ 13 | sumSequence(Vector(42, 100, 58)) should equal(200) 14 | } 15 | it("should disallow summing an empty sequence"){ 16 | evaluating { sumSequence(Vector[Int]()) } should produce[UnsupportedOperationException] 17 | } 18 | } 19 | 20 | describe("prependHello"){ 21 | it("should prepend hello to a sequence"){ 22 | prependHello(Vector[String]("Mike", "Joe", "John")) should equal(Vector("Hello, Mike", "Hello, Joe", "Hello, John")) 23 | } 24 | it("should return an empty sequence when passed an empty sequence"){ 25 | prependHello(Vector[String]()) should equal(Vector[String]()) 26 | } 27 | } 28 | 29 | describe("vowelsInWord"){ 30 | it("should return a set of vowels in a given word"){ 31 | vowelsInWord("asdfe") should equal(Set[Char]('a', 'e')) 32 | } 33 | it("should return the empty set if there are no vowels in the word"){ 34 | vowelsInWord("cfg") should equal(Set[Char]()) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /ScalaExamples/src/test/scala/com/mblinn/mbfpp/oo/iterator/LambdaBarAndGrille.scala: -------------------------------------------------------------------------------- 1 | package com.mblinn.mbfpp.oo.iterator 2 | import org.junit.runner.RunWith 3 | import org.scalatest.matchers.ShouldMatchers 4 | import org.scalatest.FunSpec 5 | import org.scalatest.junit.JUnitRunner 6 | 7 | import com.mblinn.mbfpp.oo.iterator.TheLambdaBarAndGrille._ 8 | import com.mblinn.mbfpp.oo.iterator.TheLambdaBarAndGrille.Person 9 | 10 | @RunWith(classOf[JUnitRunner]) 11 | class LambdaBarAndGrille extends FunSpec with ShouldMatchers { 12 | describe("generateGreetings") { 13 | it("should generate a list of greetings for people in the appropriate zip codes") { 14 | val expectedMessages = Vector("Hello, Mike, and welcome to the Lambda Bar And Grille!", "Hello, John, and welcome to the Lambda Bar And Grille!") 15 | val people = Vector( 16 | Person("Mike", Address(19123)), 17 | Person("John", Address(19103)), 18 | Person("Jill", Address(19098)) 19 | ) 20 | val computedMessages = generateGreetings(people) 21 | expectedMessages should equal(computedMessages) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | lazy val JavaExamples = project 2 | lazy val ScalaExamples = project 3 | -------------------------------------------------------------------------------- /project/sbt-idea-shim.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.1") 2 | --------------------------------------------------------------------------------