Skip to content

Commit e065d94

Browse files
authored
Merge pull request eugenp#4571 from den314/master
BAEL-1891 interpreter design pattern in java
2 parents 7e8dd88 + d5013d5 commit e065d94

File tree

7 files changed

+220
-0
lines changed

7 files changed

+220
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.HashMap;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.function.Function;
9+
import java.util.function.Predicate;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.Stream;
12+
13+
class Context {
14+
15+
private static Map<String, List<Row>> tables = new HashMap<>();
16+
17+
static {
18+
List<Row> list = new ArrayList<>();
19+
list.add(new Row("John", "Doe"));
20+
list.add(new Row("Jan", "Kowalski"));
21+
list.add(new Row("Dominic", "Doom"));
22+
23+
tables.put("people", list);
24+
}
25+
26+
private String table;
27+
private String column;
28+
29+
/**
30+
* Index of column to be shown in result.
31+
* Calculated in {@link #setColumnMapper()}
32+
*/
33+
private int colIndex = -1;
34+
35+
/**
36+
* Default setup, used for clearing the context for next queries.
37+
* See {@link Context#clear()}
38+
*/
39+
private static final Predicate<String> matchAnyString = s -> s.length() > 0;
40+
private static final Function<String, Stream<? extends String>> matchAllColumns = Stream::of;
41+
/**
42+
* Varies based on setup in subclasses of {@link Expression}
43+
*/
44+
private Predicate<String> whereFilter = matchAnyString;
45+
private Function<String, Stream<? extends String>> columnMapper = matchAllColumns;
46+
47+
void setColumn(String column) {
48+
this.column = column;
49+
setColumnMapper();
50+
}
51+
52+
void setTable(String table) {
53+
this.table = table;
54+
}
55+
56+
void setFilter(Predicate<String> filter) {
57+
whereFilter = filter;
58+
}
59+
60+
/**
61+
* Clears the context to defaults.
62+
* No filters, match all columns.
63+
*/
64+
void clear() {
65+
column = "";
66+
columnMapper = matchAllColumns;
67+
whereFilter = matchAnyString;
68+
}
69+
70+
List<String> search() {
71+
72+
List<String> result = tables.entrySet()
73+
.stream()
74+
.filter(entry -> entry.getKey().equalsIgnoreCase(table))
75+
.flatMap(entry -> Stream.of(entry.getValue()))
76+
.flatMap(Collection::stream)
77+
.map(Row::toString)
78+
.flatMap(columnMapper)
79+
.filter(whereFilter)
80+
.collect(Collectors.toList());
81+
82+
clear();
83+
84+
return result;
85+
}
86+
87+
/**
88+
* Sets column mapper based on {@link #column} attribute.
89+
* Note: If column is unknown, will remain to look for all columns.
90+
*/
91+
private void setColumnMapper() {
92+
switch (column) {
93+
case "*":
94+
colIndex = -1;
95+
break;
96+
case "name":
97+
colIndex = 0;
98+
break;
99+
case "surname":
100+
colIndex = 1;
101+
break;
102+
}
103+
if (colIndex != -1) {
104+
columnMapper = s -> Stream.of(s.split(" ")[colIndex]);
105+
}
106+
}
107+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.List;
4+
5+
interface Expression {
6+
List<String> interpret(Context ctx);
7+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.List;
4+
5+
class From implements Expression {
6+
7+
private String table;
8+
private Where where;
9+
10+
From(String table) {
11+
this.table = table;
12+
}
13+
14+
From(String table, Where where) {
15+
this.table = table;
16+
this.where = where;
17+
}
18+
19+
@Override
20+
public List<String> interpret(Context ctx) {
21+
ctx.setTable(table);
22+
if (where == null) {
23+
return ctx.search();
24+
}
25+
return where.interpret(ctx);
26+
}
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.List;
4+
5+
6+
public class InterpreterDemo {
7+
8+
public static void main(String[] args) {
9+
10+
Expression query = new Select("name", new From("people"));
11+
Context ctx = new Context();
12+
List<String> result = query.interpret(ctx);
13+
System.out.println(result);
14+
15+
Expression query2 = new Select("*", new From("people"));
16+
List<String> result2 = query2.interpret(ctx);
17+
System.out.println(result2);
18+
19+
Expression query3 = new Select("name", new From("people", new Where(name -> name.toLowerCase().startsWith("d"))));
20+
List<String> result3 = query3.interpret(ctx);
21+
System.out.println(result3);
22+
}
23+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.baeldung.interpreter;
2+
3+
class Row {
4+
5+
private String name;
6+
private String surname;
7+
8+
Row(String name, String surname) {
9+
this.name = name;
10+
this.surname = surname;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return name + " " + surname;
16+
}
17+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.List;
4+
5+
class Select implements Expression {
6+
7+
private String column;
8+
private From from;
9+
10+
Select(String column, From from) {
11+
this.column = column;
12+
this.from = from;
13+
}
14+
15+
@Override
16+
public List<String> interpret(Context ctx) {
17+
ctx.setColumn(column);
18+
return from.interpret(ctx);
19+
}
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.baeldung.interpreter;
2+
3+
import java.util.List;
4+
import java.util.function.Predicate;
5+
6+
class Where implements Expression {
7+
8+
private Predicate<String> filter;
9+
10+
Where(Predicate<String> filter) {
11+
this.filter = filter;
12+
}
13+
14+
@Override
15+
public List<String> interpret(Context ctx) {
16+
ctx.setFilter(filter);
17+
return ctx.search();
18+
}
19+
}

0 commit comments

Comments
 (0)