diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Context.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Context.java new file mode 100644 index 0000000000..f2416988ea --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Context.java @@ -0,0 +1,107 @@ +package com.baeldung.interpreter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Context { + + private static Map> tables = new HashMap<>(); + + static { + List list = new ArrayList<>(); + list.add(new Row("John", "Doe")); + list.add(new Row("Jan", "Kowalski")); + list.add(new Row("Dominic", "Doom")); + + tables.put("people", list); + } + + private String table; + private String column; + + /** + * Index of column to be shown in result. + * Calculated in {@link #setColumnMapper()} + */ + private int colIndex = -1; + + /** + * Default setup, used for clearing the context for next queries. + * See {@link Context#clear()} + */ + private static final Predicate matchAnyString = s -> s.length() > 0; + private static final Function> matchAllColumns = Stream::of; + /** + * Varies based on setup in subclasses of {@link Expression} + */ + private Predicate whereFilter = matchAnyString; + private Function> columnMapper = matchAllColumns; + + void setColumn(String column) { + this.column = column; + setColumnMapper(); + } + + void setTable(String table) { + this.table = table; + } + + void setFilter(Predicate filter) { + whereFilter = filter; + } + + /** + * Clears the context to defaults. + * No filters, match all columns. + */ + void clear() { + column = ""; + columnMapper = matchAllColumns; + whereFilter = matchAnyString; + } + + List search() { + + List result = tables.entrySet() + .stream() + .filter(entry -> entry.getKey().equalsIgnoreCase(table)) + .flatMap(entry -> Stream.of(entry.getValue())) + .flatMap(Collection::stream) + .map(Row::toString) + .flatMap(columnMapper) + .filter(whereFilter) + .collect(Collectors.toList()); + + clear(); + + return result; + } + + /** + * Sets column mapper based on {@link #column} attribute. + * Note: If column is unknown, will remain to look for all columns. + */ + private void setColumnMapper() { + switch (column) { + case "*": + colIndex = -1; + break; + case "name": + colIndex = 0; + break; + case "surname": + colIndex = 1; + break; + } + if (colIndex != -1) { + columnMapper = s -> Stream.of(s.split(" ")[colIndex]); + } + } +} \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Expression.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Expression.java new file mode 100644 index 0000000000..7f0893e719 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Expression.java @@ -0,0 +1,7 @@ +package com.baeldung.interpreter; + +import java.util.List; + +interface Expression { + List interpret(Context ctx); +} \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/From.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/From.java new file mode 100644 index 0000000000..d0690e3e85 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/From.java @@ -0,0 +1,27 @@ +package com.baeldung.interpreter; + +import java.util.List; + +class From implements Expression { + + private String table; + private Where where; + + From(String table) { + this.table = table; + } + + From(String table, Where where) { + this.table = table; + this.where = where; + } + + @Override + public List interpret(Context ctx) { + ctx.setTable(table); + if (where == null) { + return ctx.search(); + } + return where.interpret(ctx); + } +} \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/InterpreterDemo.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/InterpreterDemo.java new file mode 100644 index 0000000000..9b37037bb9 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/InterpreterDemo.java @@ -0,0 +1,23 @@ +package com.baeldung.interpreter; + +import java.util.List; + + +public class InterpreterDemo { + + public static void main(String[] args) { + + Expression query = new Select("name", new From("people")); + Context ctx = new Context(); + List result = query.interpret(ctx); + System.out.println(result); + + Expression query2 = new Select("*", new From("people")); + List result2 = query2.interpret(ctx); + System.out.println(result2); + + Expression query3 = new Select("name", new From("people", new Where(name -> name.toLowerCase().startsWith("d")))); + List result3 = query3.interpret(ctx); + System.out.println(result3); + } +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Row.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Row.java new file mode 100644 index 0000000000..00fd2d993a --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Row.java @@ -0,0 +1,17 @@ +package com.baeldung.interpreter; + +class Row { + + private String name; + private String surname; + + Row(String name, String surname) { + this.name = name; + this.surname = surname; + } + + @Override + public String toString() { + return name + " " + surname; + } +} \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Select.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Select.java new file mode 100644 index 0000000000..f235ce2a87 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Select.java @@ -0,0 +1,20 @@ +package com.baeldung.interpreter; + +import java.util.List; + +class Select implements Expression { + + private String column; + private From from; + + Select(String column, From from) { + this.column = column; + this.from = from; + } + + @Override + public List interpret(Context ctx) { + ctx.setColumn(column); + return from.interpret(ctx); + } +} \ No newline at end of file diff --git a/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Where.java b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Where.java new file mode 100644 index 0000000000..b31fa54cff --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/interpreter/Where.java @@ -0,0 +1,19 @@ +package com.baeldung.interpreter; + +import java.util.List; +import java.util.function.Predicate; + +class Where implements Expression { + + private Predicate filter; + + Where(Predicate filter) { + this.filter = filter; + } + + @Override + public List interpret(Context ctx) { + ctx.setFilter(filter); + return ctx.search(); + } +} \ No newline at end of file