package org.rakam.ui.report; import com.google.common.base.Optional; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.rakam.ui.DashboardService; import org.rakam.ui.ReportMetadata; import org.rakam.ui.UIPermissionParameterProvider; import org.rakam.ui.UIPermissionParameterProvider.Project; import org.rakam.ui.customreport.CustomReport; import org.rakam.ui.customreport.CustomReportMetadata; import org.rakam.ui.page.CustomPageDatabase; import org.rakam.ui.report.UIRecipe.DashboardBuilder; import org.rakam.util.AlreadyExistsException; import org.rakam.util.RakamException; import javax.inject.Inject; import java.util.List; import java.util.stream.Collectors; import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST; public class UIRecipeHandler { private final Optional<ReportMetadata> reportMetadata; private final Optional<CustomReportMetadata> customReportMetadata; private final Optional<CustomPageDatabase> customPageDatabase; private final Optional<DashboardService> dashboardService; @Inject public UIRecipeHandler( Optional<CustomReportMetadata> customReportMetadata, Optional<CustomPageDatabase> customPageDatabase, Optional<DashboardService> dashboardService, Optional<ReportMetadata> reportMetadata) { this.customReportMetadata = customReportMetadata; this.customPageDatabase = customPageDatabase; this.reportMetadata = reportMetadata; this.dashboardService = dashboardService; } public UIRecipe export(int userId, int project) { final List<Report> reports; if (reportMetadata.isPresent()) { reports = reportMetadata.get() .getReports(null, project).stream() .map(r -> new Report(r.slug, r.category, r.name, r.query, r.options, r.queryOptions, r.shared)) .collect(Collectors.toList()); } else { reports = ImmutableList.of(); } final List<CustomReport> customReports; if (customReportMetadata.isPresent()) { customReports = customReportMetadata.get().list(project).entrySet().stream().flatMap(a -> a.getValue().stream()) .map(r -> new CustomReport(r.reportType, r.name, r.data)) .collect(Collectors.toList()); } else { customReports = ImmutableList.of(); } final List<CustomPageDatabase.Page> customPages; if (customPageDatabase.isPresent()) { customPages = customPageDatabase.get() .list(project).stream() .map(r -> new CustomPageDatabase.Page(r.name, r.slug, r.category, customPageDatabase.get().get(project, r.slug))) .collect(Collectors.toList()); } else { customPages = ImmutableList.of(); } List<DashboardBuilder> dashboards; if (dashboardService.isPresent()) { dashboards = dashboardService.get().list(new Project(project, userId)).dashboards.stream() .map(a -> { List<DashboardService.DashboardItem> items = dashboardService.get() .get(new Project(project, userId), a.id).stream() .map(e -> new DashboardService.DashboardItem(e.id, e.name, e.directive, e.options, e.refreshInterval, null)) .collect(Collectors.toList()); return new DashboardBuilder(a.name, items); }) .collect(Collectors.toList()); } else { dashboards = ImmutableList.of(); } return new UIRecipe(customReports, customPages, dashboards, reports); } public void install(UIRecipe recipe, int userId, int project, boolean overrideExisting) { installInternal(recipe, userId, project, overrideExisting); } public void installInternal(UIRecipe recipe, int userId, int project, boolean overrideExisting) { recipe.getReports().stream() .forEach(report -> { try { reportMetadata.get().save(userId, project, report); } catch (AlreadyExistsException e) { if (overrideExisting) { reportMetadata.get().update(userId, project, report); } else { throw Throwables.propagate(e); } } }); Project p = new Project(project, userId); recipe.getDashboards().stream() .forEach(report -> { int dashboard; try { dashboard = dashboardService.get().create(p, report.name, null, ImmutableMap.of()).id; } catch (AlreadyExistsException e) { dashboard = dashboardService.get().list(p).dashboards.stream().filter(a -> a.name.equals(report.name)).findAny().get().id; dashboardService.get().delete(p, dashboard); dashboard = dashboardService.get().create(p, report.name, null, ImmutableMap.of()).id; } for (DashboardService.DashboardItem item : report.items) { dashboardService.get().addToDashboard(p, dashboard, item.name, item.directive, item.refreshInterval, item.options); } }); recipe.getCustomReports().stream() .forEach(customReport -> { try { customReportMetadata.get().save(userId, project, customReport); } catch (AlreadyExistsException e) { if (overrideExisting) { customReportMetadata.get().update(project, customReport); } else { throw Throwables.propagate(e); } } }); if (customPageDatabase.isPresent()) { recipe.getCustomPages().stream() .forEach(customReport -> { try { customPageDatabase.get().save(null, project, customReport); } catch (AlreadyExistsException e) { if (overrideExisting) { customPageDatabase.get().delete(project, customReport.slug); customPageDatabase.get().save(userId, project, customReport); } else { throw Throwables.propagate(e); } } }); } else if (recipe.getCustomPages().size() > 0) { throw new RakamException("Custom page feature is not supported", BAD_REQUEST); } } }