Repository: jtablesaw/tablesaw
Pull request #695 (2019-10-27 22:22:02)

#694 update documentation for Custom map functions
Thanks for contributing.

- [x] Tick to sign-off your agreement to the [Developer Certificate of Origin (DCO) 1.1](https://developercertificate.org)

## Description

Updated the documentation for Custom map functions to match the current code base

## Testing

Did you add a unit test?
No unit test. Documentation change.



Patch:
diff --git a/docs/userguide/mapping.md b/docs/userguide/mapping.md
index f8ed93da..3e72870a 100644
--- a/docs/userguide/mapping.md
+++ b/docs/userguide/mapping.md
@@ -42,35 +42,29 @@ The new Column is not added to the original columns table by default. To add it,
 
 ## Custom map functions 
 
-You can create functions that build new columns using *doWithEach():*
+You can create functions that build new columns using *map():*
 
 ```java
 Table table = Table.read().csv("../data/bush.csv");
 
 DateColumn dc1 = table.dateColumn("date");
-DateColumn dc2 = DateColumn.create("100 days later");
-
-dc1.doWithEach(localDate -> dc2.append(localDate.plusDays(100)));
+DateColumn dc2 = dc1.map(localDate -> localDate.plusDays(100)).setName("100 days later");
+table.addColumns(dc2);
 ```
 
-The method *doWithEach(Consumer<T>)* is defined on AbstractColumn. It takes a Consumer that accepts values of the same type as the column holds: LocalDates in the case of DateColumn. If the lambda syntax above is a bit too cryptic, here's a version that does the same thing with the Consumer written out as an anonymous class:
+The method *map(Function<? super T, ? extends T>)* is defined on AbstractColumn. It takes a Function that accepts values of the same type as the column holds: LocalDates in the case of DateColumn. If the lambda syntax above is a bit too cryptic, here's a version that does the same thing with the Consumer written out as an anonymous class:
 
 ```java
-DateColumn dc2 = DateColumn.create("100 days later");
-
-dc1.doWithEach(new Consumer<LocalDate>() {
+DateColumn dc2 = dc1.map(new Function<LocalDate, LocalDate>() {
     @Override
-    public void accept(LocalDate localDate) {
-        if (localDate == null) {
-            dc2.appendMissing();
-        } else {
-        	dc2.append(localDate.plusDays(100));
-        }
+    public LocalDate apply(LocalDate localDate) {
+        return localDate == null ? null : localDate.plusDays(100);
     }
-});
+}).setName("100 days later");
+table.addColumns(dc2);
 ```
 
-The accept() method here calls *plusDays(100)*  on each value in the column that receives the doWithEach method invocation and appends each result to the column d2. The results are added to the column dc2 declared just before the method is called. 
+The apply() method here calls *plusDays(100)*  on each value in the column that receives the map method invocation and appends each result to the column d2. The results are added to the column dc2 declared just before the method is called. 
 
 In writing your own map functions it's good practice to handle missing data as we do above.
 
diff --git a/jsplot/src/main/java/tech/tablesaw/plotly/components/Config.java b/jsplot/src/main/java/tech/tablesaw/plotly/components/Config.java
new file mode 100644
index 00000000..e1bbcb32
--- /dev/null
+++ b/jsplot/src/main/java/tech/tablesaw/plotly/components/Config.java
@@ -0,0 +1,58 @@
+package tech.tablesaw.plotly.components;
+
+import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Config extends Component {
+
+  private final Boolean displayModeBar;
+
+  private Config(Builder builder) {
+    this.displayModeBar = builder.displayModeBar;
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  @Override
+  public String asJavascript() {
+    Writer writer = new StringWriter();
+    PebbleTemplate compiledTemplate;
+
+    try {
+      compiledTemplate = engine.getTemplate("config_template.html");
+      compiledTemplate.evaluate(writer, getContext());
+    } catch (PebbleException | IOException e) {
+      e.printStackTrace();
+    }
+    return writer.toString();
+  }
+
+  private Map<String, Object> getContext() {
+    Map<String, Object> context = new HashMap<>();
+    context.put("displayModeBar", displayModeBar);
+    return context;
+  }
+
+  public static class Builder {
+
+    Boolean displayModeBar;
+
+    private Builder() {}
+
+    public Builder displayModeBar(boolean displayModeBar) {
+      this.displayModeBar = displayModeBar;
+      return this;
+    }
+
+    public Config build() {
+      return new Config(this);
+    }
+  }
+}
diff --git a/jsplot/src/main/java/tech/tablesaw/plotly/components/Figure.java b/jsplot/src/main/java/tech/tablesaw/plotly/components/Figure.java
index a93caae8..6ba04627 100644
--- a/jsplot/src/main/java/tech/tablesaw/plotly/components/Figure.java
+++ b/jsplot/src/main/java/tech/tablesaw/plotly/components/Figure.java
@@ -27,6 +27,7 @@ public class Figure {
 
   private final Trace[] data;
   private final Layout layout;
+  private final Config config;
   private final EventHandler[] eventHandlers;
 
   private final Map<String, Object> context = new HashMap<>();
@@ -36,27 +37,29 @@ public class Figure {
   public Figure(FigureBuilder builder) {
     this.data = builder.traces();
     this.layout = builder.layout;
+    this.config = builder.config;
     this.eventHandlers = builder.eventHandlers();
   }
 
   public Figure(Trace... traces) {
-    this.data = traces;
-    this.layout = null;
-    this.eventHandlers = null;
+    this((Layout) null, traces);
   }
 
   public Figure(Layout layout, Trace... traces) {
+    this(layout, (Config) null, traces);
+  }
+
+  public Figure(Layout layout, Config config, Trace... traces) {
     this.data = traces;
     this.layout = layout;
+    this.config = config;
     this.eventHandlers = null;
   }
 
   /** @deprecated Use the FigureBuilder instead */
   @Deprecated
   public Figure(Layout layout, EventHandler eventHandler, Trace... traces) {
-    this.data = traces;
-    this.layout = layout;
-    this.eventHandlers = new EventHandler[] {eventHandler};
+    this(layout, new EventHandler[] {eventHandler}, traces);
   }
 
   /** @deprecated Use the FigureBuilder instead */
@@ -64,6 +67,7 @@ public class Figure {
   public Figure(Layout layout, EventHandler[] eventHandlers, Trace... traces) {
     this.data = traces;
     this.layout = layout;
+    this.config = null;
     this.eventHandlers = eventHandlers;
   }
 
@@ -101,6 +105,9 @@ public class Figure {
     if (layout != null) {
       builder.append(layout.asJavascript());
     }
+    if (config != null) {
+      builder.append(config.asJavascript());
+    }
     builder.append(System.lineSeparator());
     for (int i = 0; i < data.length; i++) {
       Trace trace = data[i];
@@ -132,6 +139,10 @@ public class Figure {
       builder.append(", ");
       builder.append("layout");
     }
+    if (config != null) {
+      builder.append(", ");
+      builder.append("config");
+    }
 
     builder.append(");");
 
@@ -163,6 +174,7 @@ public class Figure {
   public static class FigureBuilder {
 
     private Layout layout;
+    private Config config;
     private List<Trace> traces = new ArrayList<>();
     private List<EventHandler> eventHandlers = new ArrayList<>();
 
@@ -171,6 +183,11 @@ public class Figure {
       return this;
     }
 
+    public FigureBuilder config(Config config) {
+      this.config = config;
+      return this;
+    }
+
     public FigureBuilder addTraces(Trace... traces) {
       this.traces.addAll(Arrays.asList(traces));
       return this;
diff --git a/jsplot/src/main/resources/config_template.html b/jsplot/src/main/resources/config_template.html
new file mode 100644
index 00000000..52564f2a
--- /dev/null
+++ b/jsplot/src/main/resources/config_template.html
@@ -0,0 +1,5 @@
+var config = {
+{% if displayModeBar is not null %}
+    displayModeBar: {{displayModeBar}}
+{% endif %}
+}
\ No newline at end of file


Test patch:
diff --git a/jsplot/src/test/java/tech/tablesaw/plotly/components/ConfigTest.java b/jsplot/src/test/java/tech/tablesaw/plotly/components/ConfigTest.java
new file mode 100644
index 00000000..535db5fd
--- /dev/null
+++ b/jsplot/src/test/java/tech/tablesaw/plotly/components/ConfigTest.java
@@ -0,0 +1,25 @@
+package tech.tablesaw.plotly.components;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+public class ConfigTest {
+
+  @Test
+  public void testJavascript() {
+    {
+      Config config = Config.builder().displayModeBar(true).build();
+      assertTrue(config.asJavascript().contains("displayModeBar: true"));
+    }
+    {
+      Config config = Config.builder().displayModeBar(false).build();
+      assertTrue(config.asJavascript().contains("displayModeBar: false"));
+    }
+    {
+      Config config = Config.builder().build();
+      assertFalse(config.asJavascript().contains("displayModeBar"));
+    }
+  }
+}