Skip to content

Commit

Permalink
TableGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
K0K0V0K committed Nov 29, 2024
1 parent 5a20d6d commit 3af89a2
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 32 deletions.
17 changes: 14 additions & 3 deletions src/main/java/koko/yayu/controller/AppController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import koko.yayu.generator.ComponentGenerator;
import koko.yayu.generator.StatisticsGenerator;
import koko.yayu.generator.TableGenerator;
import koko.yayu.service.apiservice.RestApiService;
import koko.yayu.util.YayuUtil;
import org.json.JSONObject;
Expand All @@ -28,11 +29,11 @@ public AppController(RestApiService restApiService) {
@GetMapping("/")
public String index(Model model, @RequestParam(defaultValue = "") String order) {
List<JSONObject> resp = restApiService.getApps();
YayuUtil.order(order, resp);
model.addAttribute("apps", resp);

Map<String, Long> counts = resp.stream().collect(Collectors.groupingBy(
jsonObject -> jsonObject.getString("state"),
Collectors.counting()));
model.addAttribute("counts", new TreeMap<>(counts));

model.addAttribute("topUser",
new StatisticsGenerator("User", 5, "user", resp).generate());
Expand All @@ -41,7 +42,17 @@ public String index(Model model, @RequestParam(defaultValue = "") String order)
model.addAttribute("topAppType",
new StatisticsGenerator("Application Type", 5, "applicationType", resp).generate());

model.addAttribute("counts", new TreeMap<>(counts));
model.addAttribute("table", new TableGenerator()
.addField("/id", "Id", "linktag#app")
.addField("/applicationType", "Type")
.addField("/name")
.addField("/user")
.addField("/state", "State", "appState")
.addField("/queue")
.addField("/progress", "Progress", "progress")
.addField("/startedTime", "Start", "time")
.generate(resp, order));

return "index";
}

Expand Down
6 changes: 0 additions & 6 deletions src/main/java/koko/yayu/generator/ComponentGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
public class ComponentGenerator {

private String title;
private String color = "is-primary";
private final Map<String, String> displayNames = new LinkedHashMap<>();
private final Map<String, TemplateMethodModelEx> propertyMappers = new HashMap<>();

Expand All @@ -31,11 +30,6 @@ public ComponentGenerator setTitle(String title) {
return this;
}

public ComponentGenerator setColor(String color) {
this.color = color;
return this;
}

public ComponentGenerator addField(String propertyName) {
String cleared = propertyName.replaceAll("/", "");
String capitalize = WordUtils.capitalize(cleared);
Expand Down
131 changes: 131 additions & 0 deletions src/main/java/koko/yayu/generator/TableGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package koko.yayu.generator;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import koko.yayu.config.FreeMarkerConfig;
import org.json.JSONObject;
import org.springframework.util.StringUtils;

import org.apache.commons.text.WordUtils;

public class TableGenerator {

private final Map<String, String> displayNames = new LinkedHashMap<>();
private final Map<String, TemplateMethodModelEx> propertyMappers = new HashMap<>();

public static TableGenerator create() {
return new TableGenerator();
}

public TableGenerator addField(String propertyName) {
String cleared = propertyName.replaceAll("/", "");
String capitalize = WordUtils.capitalize(cleared);
String[] words = org.apache.commons.lang3.StringUtils.splitByCharacterTypeCamelCase(capitalize);
String displayName = org.apache.commons.lang3.StringUtils.join(words, " ");
return addField(propertyName, displayName);
}

public TableGenerator addField(
String propertyName,
String displayName
) {
return addField(propertyName, displayName, null);
}

public TableGenerator addField(
String propertyName,
String displayName,
String propertyMapper
) {
displayNames.put(propertyName, displayName);
if (propertyMapper != null) {
propertyMappers.put(
propertyName,
(TemplateMethodModelEx) FreeMarkerConfig.methods.get(propertyMapper)
);
}
return this;
}

public String generate(List<JSONObject> data, String sort) {
return String.format("<table class=\"table\">%s%s</tbody></table>",
heads(), body(order(sort, data)));
}

private String heads() {
return String.format("<thead><tr>%s</tr></thead>", displayNames.keySet().stream()
.map(this::head)
.collect(Collectors.joining()));
}

private String head(String propertyName) {
return String.format("<th> %s %s %s </th>",
displayNames.get(propertyName),
linkAsc(propertyName),
linkDesc(propertyName)
);
}

private String linkAsc(String propertyName) {
return String.format("<a href=\"?order=%s-asc\"> &#8595; </a>",
propertyName.replaceAll("/", ""));
}

private String linkDesc(String propertyName) {
return String.format("<a href=\"?order=%s-desc\"> &#8593; </a>",
propertyName.replaceAll("/", ""));
}

private String body(List<JSONObject> data) {
return String.format("<tbody>%s</tbody>",
data.stream().map(this::toLine).collect(Collectors.joining()));
}

private String toLine(JSONObject jsonObject) {
return String.format("<tr>%s</tr>", displayNames.keySet().stream()
.map(prop -> getField(jsonObject, prop))
.collect(Collectors.joining()));
}

private String getField(JSONObject jsonObject, String propertyName) {
return String.format("<td>%s</td>", getValue(jsonObject, propertyName));
}

private String getValue(JSONObject data, String key) {
String[] split = key.split("#");
Object re = data.query(split[0]);
TemplateMethodModelEx mapper = propertyMappers.get(key);
if (mapper != null) {
try {
re = mapper.exec(Stream.concat(
Stream.of(split).skip(1),
Stream.of(re)
).toList());
} catch (TemplateModelException e) {
throw new RuntimeException(e);
//TODO
}
}
return String.valueOf(re);
}

private List<JSONObject> order(String order, List<JSONObject> list) {
if (StringUtils.hasLength(order)) {
String[] params = order.split("-");
list.sort(Comparator.comparing(o -> o.get(params[0]).toString()));
if ("desc".equals(params[1])) {
Collections.reverse(list);
}
}
return list;
}
}
10 changes: 8 additions & 2 deletions src/main/java/koko/yayu/service/apiservice/RestApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import koko.yayu.config.YayuConfig;
import koko.yayu.util.YayuUtil;
import org.json.JSONObject;
Expand All @@ -25,6 +27,11 @@ public class RestApiService extends AbstractApiService {
.build(CacheLoader.from(token ->
get("cluster/userinfo", YayuUtil.jsonObjectMapper("clusterUserInfo"))));

LoadingCache<String, List<JSONObject>> appsCache = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.SECONDS)
.build(CacheLoader.from(token ->
get("cluster/apps", YayuUtil.jsonListMapper("apps", "app"))));

public RestApiService(YayuConfig config) {
super(config.getMrUrl(), "/ws/v1/", 16);
}
Expand All @@ -48,8 +55,7 @@ public List<JSONObject> getNodes() {
}

public List<JSONObject> getApps() {
return get("cluster/apps",
YayuUtil.jsonListMapper("apps", "app"));
return appsCache.getUnchecked(YayuUtil.getAuthToken());
}

public JSONObject getApp(String appId) {
Expand Down
22 changes: 1 addition & 21 deletions src/main/resources/templates/index.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,7 @@
</div>
</div>
<div class="table-container">
<table class="table">
<thead>
<tr>
${tableHead("id", "applicationType", "name", "user", "state", "queue", "progress", "startedTime")}
</tr>
</thead>
<tbody>
<#list apps as app>
<tr>
<td>${linkTag("app", app.id)}</td>
<td>${app.applicationType}</td>
<td>${app.name}</td>
<td>${app.user}</td>
<td>${appState(app.state)}</td>
<td>${app.queue}</td>
<td>${progress(app.progress)}</td>
<td>${time(app.startedTime)}</td>
</tr>
</#list>
</tbody>
</table>
${table}
</div>
</div>
</div>
Expand Down

0 comments on commit 3af89a2

Please sign in to comment.