001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019 */
020package org.sonar.server.startup;
021
022import com.google.common.collect.Lists;
023import com.google.common.collect.Ordering;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026import org.sonar.api.utils.TimeProfiler;
027import org.sonar.api.web.Dashboard;
028import org.sonar.api.web.DashboardTemplate;
029import org.sonar.core.dashboard.ActiveDashboardDao;
030import org.sonar.core.dashboard.ActiveDashboardDto;
031import org.sonar.core.dashboard.DashboardDao;
032import org.sonar.core.dashboard.DashboardDto;
033import org.sonar.core.dashboard.WidgetDto;
034import org.sonar.core.dashboard.WidgetPropertyDto;
035import org.sonar.core.template.LoadedTemplateDao;
036import org.sonar.core.template.LoadedTemplateDto;
037
038import java.io.Serializable;
039import java.util.Date;
040import java.util.List;
041import java.util.Map.Entry;
042
043/**
044 * @since 2.13
045 */
046public final class RegisterNewDashboards {
047  private static final Logger LOG = LoggerFactory.getLogger(RegisterNewDashboards.class);
048  static final String DEFAULT_DASHBOARD_NAME = "Dashboard";
049
050  private final List<DashboardTemplate> dashboardTemplates;
051  private final DashboardDao dashboardDao;
052  private final ActiveDashboardDao activeDashboardDao;
053  private final LoadedTemplateDao loadedTemplateDao;
054
055  public RegisterNewDashboards(DashboardTemplate[] dashboardTemplatesArray, DashboardDao dashboardDao,
056      ActiveDashboardDao activeDashboardDao, LoadedTemplateDao loadedTemplateDao) {
057    this.dashboardTemplates = Lists.newArrayList(dashboardTemplatesArray);
058    this.dashboardDao = dashboardDao;
059    this.activeDashboardDao = activeDashboardDao;
060    this.loadedTemplateDao = loadedTemplateDao;
061  }
062
063  public void start() {
064    TimeProfiler profiler = new TimeProfiler().start("Register dashboards");
065
066    List<DashboardDto> registeredDashboards = Lists.newArrayList();
067    for (DashboardTemplate template : dashboardTemplates) {
068      if (shouldRegister(template.getName())) {
069        Dashboard dashboard = template.createDashboard();
070        DashboardDto dto = register(template.getName(), dashboard);
071        if ((dto != null) && (dashboard.isActivated())) {
072          registeredDashboards.add(dto);
073        }
074      }
075    }
076
077    activate(registeredDashboards);
078
079    profiler.stop();
080  }
081
082  protected void activate(List<DashboardDto> loadedDashboards) {
083    int nextOrderIndex = activeDashboardDao.selectMaxOrderIndexForNullUser() + 1;
084
085    for (DashboardDto dashboardDto : new DashboardOrdering().sortedCopy(loadedDashboards)) {
086      activate(dashboardDto, nextOrderIndex++);
087    }
088  }
089
090  private void activate(DashboardDto dashboardDto, int index) {
091    ActiveDashboardDto activeDashboardDto = new ActiveDashboardDto()
092        .setDashboardId(dashboardDto.getId())
093        .setOrderIndex(index);
094    activeDashboardDao.insert(activeDashboardDto);
095
096    LOG.info("New dashboard '" + dashboardDto.getName() + "' registered");
097  }
098
099  protected DashboardDto register(String name, Dashboard dashboard) {
100    DashboardDto dto = null;
101    if (dashboardDao.selectGlobalDashboard(name) == null) {
102      dto = createDtoFromExtension(name, dashboard);
103      dashboardDao.insert(dto);
104    }
105    // and save the fact that is has now already been loaded
106    loadedTemplateDao.insert(new LoadedTemplateDto(name, LoadedTemplateDto.DASHBOARD_TYPE));
107    return dto;
108  }
109
110  protected DashboardDto createDtoFromExtension(String name, Dashboard dashboard) {
111    Date now = new Date();
112
113    DashboardDto dashboardDto = new DashboardDto()
114        .setName(name)
115        .setDescription(dashboard.getDescription())
116        .setColumnLayout(dashboard.getLayout().getCode())
117        .setShared(true)
118        .setGlobal(dashboard.isGlobal())
119        .setCreatedAt(now)
120        .setUpdatedAt(now);
121
122    for (int columnIndex = 1; columnIndex <= dashboard.getLayout().getColumns(); columnIndex++) {
123      List<Dashboard.Widget> widgets = dashboard.getWidgetsOfColumn(columnIndex);
124      for (int rowIndex = 1; rowIndex <= widgets.size(); rowIndex++) {
125        Dashboard.Widget widget = widgets.get(rowIndex - 1);
126        WidgetDto widgetDto = new WidgetDto()
127            .setKey(widget.getId())
128            .setColumnIndex(columnIndex)
129            .setRowIndex(rowIndex)
130            .setConfigured(true)
131            .setCreatedAt(now)
132            .setUpdatedAt(now);
133        dashboardDto.addWidget(widgetDto);
134
135        for (Entry<String, String> property : widget.getProperties().entrySet()) {
136          WidgetPropertyDto propDto = new WidgetPropertyDto()
137              .setKey(property.getKey())
138              .setValue(property.getValue());
139          widgetDto.addWidgetProperty(propDto);
140        }
141      }
142    }
143    return dashboardDto;
144  }
145
146  protected boolean shouldRegister(String dashboardName) {
147    return loadedTemplateDao.countByTypeAndKey(LoadedTemplateDto.DASHBOARD_TYPE, dashboardName) == 0;
148  }
149
150  private static class DashboardOrdering extends Ordering<DashboardDto> implements Serializable {
151    private static final long serialVersionUID = 0;
152
153    @Override
154    public int compare(DashboardDto left, DashboardDto right) {
155      String leftName = (left == null) ? null : left.getName();
156      String rightName = (right == null) ? null : right.getName();
157
158      // the default dashboard must be the first one to be activated
159      if (DEFAULT_DASHBOARD_NAME.equals(leftName)) {
160        return -1;
161      }
162      if (DEFAULT_DASHBOARD_NAME.equals(rightName)) {
163        return 1;
164      }
165
166      return Ordering.natural().nullsLast().compare(leftName, rightName);
167    }
168  }
169}