Overhaul: finish extracting logic from view

This commit is contained in:
f43nd1r 2018-05-22 04:17:21 +02:00
parent 34771f23ff
commit 3c1f65dc99
12 changed files with 114 additions and 93 deletions

View file

@ -8,11 +8,13 @@ import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.lang.NonNull;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import java.util.ArrayList;
@ -24,14 +26,15 @@ import java.util.List;
*/
@MappedSuperclass
public abstract class BaseBug {
@Type(type = "text") protected String title;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}, optional = false, fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
private App app;
private boolean solved;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "bug_stacktraces", joinColumns = @JoinColumn(name = "bug_id", referencedColumnName = "id"))
@Type(type = "text")
private List<String> stacktraces;
@Type(type = "text") protected String title;
private int versionCode;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

View file

@ -48,7 +48,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -109,6 +108,20 @@ public class DataService implements Serializable {
onlyNonSolved ? () -> bugViewRepository.countAllByAppAndSolvedFalse(app) : () -> bugViewRepository.countAllByApp(app));
}
@NonNull
public ObservableDataProvider<Report, Void> getReportProvider(@NonNull BaseBug bug) {
return new BufferedDataProvider<>(acraConfiguration.getPaginationSize(),
pageable -> reportRepository.findAllByBugId(bug.getId(), pageable),
() -> reportRepository.countByBugId(bug.getId()));
}
@NonNull
public ObservableDataProvider<Report, Void> getReportProvider(@NonNull App app) {
return new BufferedDataProvider<>(acraConfiguration.getPaginationSize(),
pageable -> reportRepository.findAllByBugApp(app, pageable),
() -> reportRepository.countByBugApp(app));
}
@NonNull
public ObservableDataProvider<ProguardMapping, Void> getMappingProvider(@NonNull App app) {
return new BufferedDataProvider<>(acraConfiguration.getPaginationSize(),
@ -144,7 +157,7 @@ public class DataService implements Serializable {
bug.setTitle(title);
bug.setStacktraces(bugRepository.loadStacktraces(bugs));
bugRepository.save(bug);
try (Stream<Report> stream = reportRepository.streamAllByBugIn(list)) {
try (Stream<Report> stream = reportRepository.streamAllByBugIdIn(list.stream().map(BaseBug::getId).collect(Collectors.toList()))) {
stream.forEach(report -> {
report.setBug(bug);
reportRepository.save(report);
@ -153,11 +166,6 @@ public class DataService implements Serializable {
bugRepository.deleteAllByIdIn(list.stream().map(BaseBug::getId).collect(Collectors.toList()));
}
@NonNull
public Optional<Date> getLatestReportDate(@NonNull Bug bug) {
return reportRepository.maxDateByBug(bug);
}
@Transactional
public void setBugSolved(@NonNull BaseBug bug, boolean solved) {
Bug b = bugRepository.getOne(bug.getId());
@ -166,7 +174,26 @@ public class DataService implements Serializable {
}
@NonNull
public Optional<App> findAppById(@NonNull String encodedId) {
public Optional<ProguardMapping> findMapping(@NonNull App app, int versionCode) {
return mappingRepository.findById(new ProguardMapping.MetaData(app, versionCode));
}
@NonNull
public Optional<Report> findReport(@NonNull String id) {
return reportRepository.findByIdEager(id);
}
@NonNull
public Optional<VBug> findBug(@NonNull String encodedId) {
try {
return bugViewRepository.findByIdEager(Integer.parseInt(encodedId));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
@NonNull
public Optional<App> findApp(@NonNull String encodedId) {
try {
return appRepository.findById(Integer.parseInt(encodedId));
} catch (NumberFormatException e) {
@ -174,10 +201,16 @@ public class DataService implements Serializable {
}
}
@NonNull
public List<App> findAllApps() {
return appRepository.findAll();
}
@NonNull
public List<Attachment> findAttachments(@NonNull Report report) {
return attachmentRepository.findAllByReport(report);
}
@Transactional
public void changeConfiguration(@NonNull App app, @NonNull App.Configuration configuration) {
app.setConfiguration(configuration);
@ -208,6 +241,10 @@ public class DataService implements Serializable {
appRepository.delete(app);
}
public void delete(@NonNull Report report) {
reportRepository.delete(report);
}
public void delete(@NonNull ProguardMapping mapping) {
mappingRepository.delete(mapping);
}

View file

@ -5,8 +5,11 @@ import com.faendir.acra.model.view.VBug;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.lang.NonNull;
import java.util.Optional;
/**
* @author lukas
* @since 17.05.18
@ -19,4 +22,7 @@ public interface BugViewRepository extends JpaRepository<VBug, Integer> {
int countAllByApp(@NonNull App app);
int countAllByAppAndSolvedFalse(@NonNull App app);
@Query("select bug from VBug bug join fetch bug.app join fetch bug.stacktraces where bug.id = ?1")
Optional<VBug> findByIdEager(int id);
}

View file

@ -1,9 +1,7 @@
package com.faendir.acra.sql.data;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.Report;
import com.faendir.acra.model.base.BaseBug;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
@ -36,12 +34,9 @@ public interface ReportRepository extends JpaRepository<Report, String> {
int countByBugApp(@NonNull App app);
Slice<Report> findAllByBug(@NonNull Bug bug, @NonNull Pageable pageable);
Slice<Report> findAllByBugId(@NonNull int bug, @NonNull Pageable pageable);
Stream<Report> streamAllByBugIn(@NonNull List<? extends BaseBug> bugs);
Stream<Report> streamAllByBugIdIn(@NonNull List<Integer> bugs);
int countByBug(@NonNull Bug bug);
@Query("select max(report.date) from Report report where report.bug = ?1")
Optional<Date> maxDateByBug(@NonNull Bug bug);
int countByBugId(@NonNull int bug);
}

View file

@ -70,7 +70,7 @@ public class AppView extends ParametrizedBaseView<Pair<App, String>> {
protected Pair<App, String> parseParameter(String parameter) {
String[] parameters = parameter.split(MyNavigator.SEPARATOR);
if (parameters.length > 0) {
Optional<App> app = dataService.findAppById(parameters[0]);
Optional<App> app = dataService.findApp(parameters[0]);
if (app.isPresent()) {
return Pair.of(app.get(), parameters.length == 1 ? "" : parameters[1]);
}

View file

@ -1,8 +1,7 @@
package com.faendir.acra.ui.view.app.tabs;
import com.faendir.acra.dataprovider.BufferedDataProvider;
import com.faendir.acra.sql.data.ReportRepository;
import com.faendir.acra.model.App;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.ui.navigation.NavigationManager;
import com.faendir.acra.ui.view.base.ReportList;
import com.vaadin.spring.annotation.SpringComponent;
@ -18,19 +17,16 @@ import org.springframework.lang.NonNull;
@SpringComponent
@ViewScope
public class ReportTab implements AppTab {
@NonNull private final ReportRepository reportRepository;
@NonNull private final BufferedDataProvider.Factory factory;
@NonNull private final DataService dataService;
@Autowired
public ReportTab(@NonNull ReportRepository reportRepository, @NonNull BufferedDataProvider.Factory factory) {
this.reportRepository = reportRepository;
this.factory = factory;
public ReportTab(@NonNull DataService dataService) {
this.dataService = dataService;
}
@Override
public Component createContent(@NonNull App app, @NonNull NavigationManager navigationManager) {
Component content = new ReportList(app, navigationManager, reportRepository::delete,
factory.create(app, reportRepository::findAllByBugApp, reportRepository::countByBugApp));
Component content = new ReportList(app, navigationManager, dataService::delete, dataService.getReportProvider(app));
content.setSizeFull();
return content;
}

View file

@ -1,10 +1,9 @@
package com.faendir.acra.ui.view.bug;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.Permission;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.sql.data.BugRepository;
import com.faendir.acra.ui.annotation.RequiresAppPermission;
import com.faendir.acra.ui.navigation.MyNavigator;
import com.faendir.acra.ui.navigation.SingleParametrizedViewProvider;
@ -37,31 +36,27 @@ import java.util.Optional;
@SpringComponent
@ViewScope
@RequiresAppPermission(Permission.Level.VIEW)
public class BugView extends ParametrizedBaseView<Pair<Bug, String>> {
public class BugView extends ParametrizedBaseView<Pair<VBug, String>> {
private final List<BugTab> tabs;
@NonNull private final DataService dataService;
@Autowired
public BugView(@NonNull @Lazy List<BugTab> tabs, @NonNull DataService dataService) {
public BugView(@NonNull @Lazy List<BugTab> tabs) {
this.tabs = tabs;
this.dataService = dataService;
}
@Override
protected void enter(@NonNull Pair<Bug, String> parameter) {
Bug bug = parameter.getFirst();
protected void enter(@NonNull Pair<VBug, String> parameter) {
VBug bug = parameter.getFirst();
GridLayout summaryGrid = new GridLayout(2, 1);
Style.BORDERED_GRIDLAYOUT.apply(summaryGrid);
summaryGrid.addComponents(new Label("Title", ContentMode.PREFORMATTED), new Label(bug.getTitle(), ContentMode.PREFORMATTED));
summaryGrid.addComponents(new Label("Version", ContentMode.PREFORMATTED), new Label(String.valueOf(bug.getVersionCode()), ContentMode.PREFORMATTED));
dataService.getLatestReportDate(bug)
.ifPresent(date -> summaryGrid.addComponents(new Label("Last Report", ContentMode.PREFORMATTED),
new Label(new PrettyTime().format(date), ContentMode.PREFORMATTED)));
summaryGrid.addComponents(new Label("Last Report", ContentMode.PREFORMATTED), new Label(new PrettyTime().format(bug.getLastReport()), ContentMode.PREFORMATTED));
summaryGrid.setDefaultComponentAlignment(Alignment.MIDDLE_LEFT);
summaryGrid.setSizeFull();
Panel summary = new Panel(summaryGrid);
summary.setCaption("Summary");
MyTabSheet<Bug> tabSheet = new MyTabSheet<>(bug, getNavigationManager(), tabs);
MyTabSheet<VBug> tabSheet = new MyTabSheet<>(bug, getNavigationManager(), tabs);
tabSheet.setSizeFull();
tabSheet.addSelectedTabChangeListener(e -> getNavigationManager().updatePageParameters(bug.getId() + "/" + e.getTabSheet().getSelectedTab().getCaption()));
if (tabSheet.getCaptions().contains(parameter.getSecond())) tabSheet.setInitialTab(parameter.getSecond());
@ -79,44 +74,41 @@ public class BugView extends ParametrizedBaseView<Pair<Bug, String>> {
@SpringComponent
@UIScope
public static class Provider extends SingleParametrizedViewProvider<Pair<Bug, String>, BugView> {
@NonNull private final BugRepository bugRepository;
public static class Provider extends SingleParametrizedViewProvider<Pair<VBug, String>, BugView> {
@NonNull private final DataService dataService;
@Autowired
public Provider(@NonNull BugRepository bugRepository) {
public Provider(@NonNull DataService dataService) {
super(BugView.class);
this.bugRepository = bugRepository;
this.dataService = dataService;
}
@Override
protected String getTitle(Pair<Bug, String> parameter) {
protected String getTitle(Pair<VBug, String> parameter) {
String title = parameter.getFirst().getTitle();
if (title.length() > 100) title = title.substring(0, 95) + "";
return title;
}
@Override
protected boolean isValidParameter(Pair<Bug, String> parameter) {
protected boolean isValidParameter(Pair<VBug, String> parameter) {
return parameter != null;
}
@Override
protected Pair<Bug, String> parseParameter(String parameter) {
try {
String[] parameters = parameter.split(MyNavigator.SEPARATOR);
if (parameters.length > 0) {
Optional<Bug> bug = bugRepository.findByIdEager(Integer.parseInt(parameters[0]));
if (bug.isPresent()) {
return Pair.of(bug.get(), parameters.length == 1 ? "" : parameters[1]);
}
protected Pair<VBug, String> parseParameter(String parameter) {
String[] parameters = parameter.split(MyNavigator.SEPARATOR);
if (parameters.length > 0) {
Optional<VBug> bug = dataService.findBug(parameters[0]);
if (bug.isPresent()) {
return Pair.of(bug.get(), parameters.length == 1 ? "" : parameters[1]);
}
} catch (IllegalArgumentException ignored) {
}
return null;
}
@Override
protected App toApp(Pair<Bug, String> parameter) {
protected App toApp(Pair<VBug, String> parameter) {
return parameter.getFirst().getApp();
}

View file

@ -1,6 +1,6 @@
package com.faendir.acra.ui.view.bug.tabs;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.ui.view.base.MyTabSheet;
import java.io.Serializable;
@ -9,5 +9,5 @@ import java.io.Serializable;
* @author Lukas
* @since 27.03.2018
*/
public interface BugTab extends MyTabSheet.Tab<Bug>, Serializable {
public interface BugTab extends MyTabSheet.Tab<VBug>, Serializable {
}

View file

@ -1,8 +1,7 @@
package com.faendir.acra.ui.view.bug.tabs;
import com.faendir.acra.dataprovider.BufferedDataProvider;
import com.faendir.acra.sql.data.ReportRepository;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.ui.navigation.NavigationManager;
import com.faendir.acra.ui.view.base.ReportList;
import com.vaadin.spring.annotation.SpringComponent;
@ -18,19 +17,16 @@ import org.springframework.lang.NonNull;
@SpringComponent("bugReportTab")
@ViewScope
public class ReportTab implements BugTab {
@NonNull private final ReportRepository reportRepository;
@NonNull private final BufferedDataProvider.Factory factory;
@NonNull private final DataService dataService;
@Autowired
public ReportTab(@NonNull ReportRepository reportRepository, @NonNull BufferedDataProvider.Factory factory) {
this.reportRepository = reportRepository;
this.factory = factory;
public ReportTab(@NonNull DataService dataService) {
this.dataService = dataService;
}
@Override
public Component createContent(@NonNull Bug bug, @NonNull NavigationManager navigationManager) {
Component content = new ReportList(bug.getApp(), navigationManager, reportRepository::delete,
factory.create(bug, reportRepository::findAllByBug, reportRepository::countByBug));
public Component createContent(@NonNull VBug bug, @NonNull NavigationManager navigationManager) {
Component content = new ReportList(bug.getApp(), navigationManager, dataService::delete, dataService.getReportProvider(bug));
content.setSizeFull();
return content;
}

View file

@ -1,8 +1,8 @@
package com.faendir.acra.ui.view.bug.tabs;
import com.faendir.acra.sql.data.ProguardMappingRepository;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.ProguardMapping;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.ui.navigation.NavigationManager;
import com.faendir.acra.util.Utils;
import com.vaadin.shared.ui.ContentMode;
@ -23,16 +23,16 @@ import java.util.Optional;
@SpringComponent
@ViewScope
public class StackTraceTab implements BugTab {
@NonNull private final ProguardMappingRepository mappingRepository;
@NonNull private final DataService dataService;
@Autowired
public StackTraceTab(@NonNull ProguardMappingRepository mappingRepository) {
this.mappingRepository = mappingRepository;
public StackTraceTab(@NonNull DataService dataService) {
this.dataService = dataService;
}
@Override
public Component createContent(@NonNull Bug bug, @NonNull NavigationManager navigationManager) {
Optional<ProguardMapping> mapping = mappingRepository.findById(bug.getApp(), bug.getVersionCode());
public Component createContent(@NonNull VBug bug, @NonNull NavigationManager navigationManager) {
Optional<ProguardMapping> mapping = dataService.findMapping(bug.getApp(), bug.getVersionCode());
Accordion accordion = new Accordion();
for (String stacktrace : bug.getStacktraces()) {
if (mapping.isPresent()) {

View file

@ -1,7 +1,7 @@
package com.faendir.acra.ui.view.bug.tabs;
import com.faendir.acra.model.Bug;
import com.faendir.acra.model.QReport;
import com.faendir.acra.model.view.VBug;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.ui.navigation.NavigationManager;
import com.faendir.acra.ui.view.base.Statistics;
@ -28,8 +28,8 @@ public class StatisticsTab implements BugTab {
}
@Override
public Component createContent(@NonNull Bug bug, @NonNull NavigationManager navigationManager) {
Panel root = new Panel(new Statistics(QReport.report.bug.eq(bug), dataService));
public Component createContent(@NonNull VBug bug, @NonNull NavigationManager navigationManager) {
Panel root = new Panel(new Statistics(QReport.report.bug.id.eq(bug.getId()), dataService));
root.setSizeFull();
Style.apply(root, Style.NO_BACKGROUND, Style.NO_BORDER);
return root;

View file

@ -2,17 +2,15 @@ package com.faendir.acra.ui.view.report;
import com.diffplug.common.base.Errors;
import com.diffplug.common.base.Throwing;
import com.faendir.acra.sql.data.AttachmentRepository;
import com.faendir.acra.sql.data.ProguardMappingRepository;
import com.faendir.acra.sql.data.ReportRepository;
import com.faendir.acra.model.App;
import com.faendir.acra.model.Attachment;
import com.faendir.acra.model.Permission;
import com.faendir.acra.model.ProguardMapping;
import com.faendir.acra.model.Report;
import com.faendir.acra.service.data.DataService;
import com.faendir.acra.ui.annotation.RequiresAppPermission;
import com.faendir.acra.ui.view.base.ParametrizedBaseView;
import com.faendir.acra.ui.navigation.SingleParametrizedViewProvider;
import com.faendir.acra.ui.view.base.ParametrizedBaseView;
import com.faendir.acra.util.Style;
import com.faendir.acra.util.Utils;
import com.vaadin.server.FileDownloader;
@ -48,19 +46,17 @@ import java.util.stream.Stream;
@ViewScope
@RequiresAppPermission(Permission.Level.VIEW)
public class ReportView extends ParametrizedBaseView<Report> {
@NonNull private final AttachmentRepository attachmentRepository;
@NonNull private final ProguardMappingRepository mappingRepository;
@NonNull private final DataService dataService;
@Autowired
public ReportView(@NonNull AttachmentRepository attachmentRepository, @NonNull ProguardMappingRepository mappingRepository) {
this.attachmentRepository = attachmentRepository;
this.mappingRepository = mappingRepository;
public ReportView(@NonNull DataService dataService) {
this.dataService = dataService;
}
@Override
protected void enter(@NonNull Report parameter) {
HorizontalLayout attachments = new HorizontalLayout();
for (Attachment file : attachmentRepository.findAllByReport(parameter)) {
for (Attachment file : dataService.findAttachments(parameter)) {
Button button = new Button(file.getFilename());
new FileDownloader(new StreamResource(new ExceptionAwareStreamSource(file.getContent()::getBinaryStream), file.getFilename())).extend(button);
attachments.addComponent(button);
@ -71,7 +67,7 @@ public class ReportView extends ParametrizedBaseView<Report> {
summaryGrid.addComponents(new Label("Version", ContentMode.PREFORMATTED), new Label(parameter.getVersionName(), ContentMode.PREFORMATTED));
summaryGrid.addComponents(new Label("Email", ContentMode.PREFORMATTED), new Label(parameter.getUserEmail(), ContentMode.PREFORMATTED));
summaryGrid.addComponents(new Label("Comment", ContentMode.PREFORMATTED), new Label(parameter.getUserComment(), ContentMode.PREFORMATTED));
Optional<ProguardMapping> mapping = mappingRepository.findById(parameter.getBug().getApp(), parameter.getVersionCode());
Optional<ProguardMapping> mapping = dataService.findMapping(parameter.getBug().getApp(), parameter.getVersionCode());
if (mapping.isPresent()) {
summaryGrid.addComponents(new Label("De-obfuscated Stacktrace", ContentMode.PREFORMATTED),
new Label(Utils.retrace(parameter.getStacktrace(), mapping.get().getMappings()), ContentMode.PREFORMATTED));
@ -147,12 +143,12 @@ public class ReportView extends ParametrizedBaseView<Report> {
@SpringComponent
@UIScope
public static class Provider extends SingleParametrizedViewProvider<Report, ReportView> {
@NonNull private final ReportRepository reportRepository;
@NonNull private final DataService dataService;
@Autowired
public Provider(@NonNull ReportRepository reportRepository) {
public Provider(@NonNull DataService dataService) {
super(ReportView.class);
this.reportRepository = reportRepository;
this.dataService = dataService;
}
@Override
@ -167,7 +163,7 @@ public class ReportView extends ParametrizedBaseView<Report> {
@Override
protected Report parseParameter(String parameter) {
return reportRepository.findByIdEager(parameter).orElse(null);
return dataService.findReport(parameter).orElse(null);
}
@Override