package de.otto.edison.status.controller; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import de.otto.edison.status.domain.*; import org.springframework.web.bind.ServletRequestUtils; import org.springframework.web.servlet.support.RequestContextUtils; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; import static org.springframework.web.servlet.support.ServletUriComponentsBuilder.fromCurrentContextPath; @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(NON_NULL) public class StatusRepresentation { private static final Pattern STATUS_DETAIL_JSON_SEPARATOR_PATTERN = Pattern.compile("\\s(.)"); public ApplicationRepresentation application; public ClusterInfo cluster; public SystemInfo system; public TeamInfo team; public List<ServiceSpec> serviceSpecs; private StatusRepresentation(final ApplicationStatus applicationStatus) { this.application = new ApplicationRepresentation(applicationStatus); this.system = applicationStatus.system; this.team = applicationStatus.team; this.serviceSpecs = applicationStatus.serviceSpecs; this.cluster = applicationStatus.cluster.isEnabled() ? applicationStatus.cluster : null; } public static StatusRepresentation statusRepresentationOf(final ApplicationStatus status) { return new StatusRepresentation(status); } private Map<String, ?> statusDetailsOf(final List<StatusDetail> statusDetails) { final Map<String, Object> map = new LinkedHashMap<>(); for (StatusDetail entry : statusDetails) { final List<Map<String, String>> links = toLinks(entry.getLinks()); map.put(toCamelCase(entry.getName()), new LinkedHashMap<String, Object>() {{ put("status", entry.getStatus().name()); put("message", entry.getMessage()); put("links", links); putAll(entry.getDetails().entrySet().stream().collect(Collectors.toMap(entry -> toCamelCase(entry.getKey()), Map.Entry::getValue))); }}); } return map; } private List<Map<String, String>> toLinks(final List<Link> links) { final List<Map<String,String>> result = new ArrayList<>(); links.forEach(link -> result.add(new LinkedHashMap<String,String>() {{ put("rel", link.rel); put("href", link.href.startsWith("http") ? link.href : fromCurrentContextPath().path(link.href).build().toString()); put("title", link.title); }})); return result; } private static String toCamelCase(final String name) { Matcher matcher = STATUS_DETAIL_JSON_SEPARATOR_PATTERN.matcher(name); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, matcher.group(1).toUpperCase()); } matcher.appendTail(sb); String s = sb.toString(); return s.substring(0,1).toLowerCase() + s.substring(1); } @JsonIgnoreProperties(ignoreUnknown = true) class ApplicationRepresentation { public String name; public String title; public String description; public String group; public String environment; public String version; public String commit; public String vcsUrl; public Status status; public Map<String,?> statusDetails; public ApplicationRepresentation() { } private ApplicationRepresentation(final ApplicationStatus applicationStatus) { this.name = applicationStatus.application.name; this.title = applicationStatus.application.title; this.description = applicationStatus.application.description; this.group = applicationStatus.application.group; this.environment = applicationStatus.application.environment; this.version = applicationStatus.vcs.version; this.commit = applicationStatus.vcs.commit; this.vcsUrl = applicationStatus.vcs.url; this.status = applicationStatus.status; this.statusDetails = statusDetailsOf(applicationStatus.statusDetails); } } }