long width = (Long) displayValues[2];
s.append(html);
// Top row (special case)
Axis topAxis = axes.get(0);
List<Column> topColumns = topAxis.getColumns();
final int topColumnSize = topColumns.size();
final String topAxisName = topAxis.getName();
if (axes.size() == 1)
{ // Ensure that one dimension is vertically down the page
s.append(" <th data-id=\"a").append(topAxis.getId()).append("\" class=\"th-ncube ncube-head\">");
s.append(" <div class=\"btn-group axis-menu\" data-id=\"").append(topAxisName).append("\">\n");
s.append(" <button type=\"button\" class=\"btn-sm btn-primary dropdown-toggle axis-btn\" data-toggle=\"dropdown\">");
s.append(" <span>").append(topAxisName).append("</span><span class=\"caret\"></span>");
s.append(" </button></th>\n");
s.append(" </div>\n");
s.append(" <th class=\"th-ncube ncube-dead\">");
s.append(ncube.getName());
s.append("</th>\n");
s.append("</tr>\n");
for (int i = 0; i < width; i++)
{
s.append("<tr>\n");
Column column = topColumns.get(i);
boolean isCmd = isColumnInlineExpression(column);
String colId = String.valueOf(column.getId());
s.append(" <th data-id=\"").append(colId);
s.append("\" data-axis=\"").append(topAxisName).append("\" class=\"th-ncube ");
s.append(getColumnCssClass(topAxis, column));
s.append("\">");
if (isCmd)
{
s.append("<pre class=\"ncube-pre\">");
}
addColumnPrefixText(s, column);
s.append(column.isDefault() ? "Default" : column.toString());
if (isCmd)
{
s.append("</pre>");
}
s.append("</th>\n");
Set<Long> colIds = new LinkedHashSet<>();
colIds.add(column.getId());
buildCell(ncube, s, colIds);
s.append("</tr>\n");
}
}
else
{ // 2D+ shows as one column on the X axis and all other dimensions on the Y axis.
int deadCols = axes.size() - 1;
if (deadCols > 0)
{
s.append(" <th class=\"th-ncube ncube-dead\" colspan=\"").append(deadCols).append("\">");
s.append(ncube.getName());
s.append("</th>\n");
}
s.append(" <th data-id=\"a").append(topAxis.getId()).append("\" class=\"th-ncube ncube-head\" colspan=\"");
s.append(topAxis.size());
s.append("\">");
s.append(" <div class=\"btn-group axis-menu\" data-id=\"").append(topAxisName).append("\">\n");
s.append(" <button type=\"button\" class=\"btn-sm btn-primary dropdown-toggle axis-btn\" data-toggle=\"dropdown\">");
s.append(" <span>").append(topAxisName).append("</span><span class=\"caret\"></span>");
s.append(" </button>\n");
s.append(" </div>\n");
s.append(" </th>\n</tr>\n");
// Second row (special case)
s.append("<tr>\n");
Map<String, Long> rowspanCounter = new HashMap<>();
Map<String, Long> rowspan = new HashMap<>();
Map<String, Long> columnCounter = new HashMap<>();
Map<String, List<Column>> columns = new HashMap<>();
final int axisCount = axes.size();
for (int i = 1; i < axisCount; i++)
{
Axis axis = axes.get(i);
String axisName = axis.getName();
s.append(" <th data-id=\"a").append(axis.getId()).append("\" class=\"th-ncube ncube-head\">\n");
s.append(" <div class=\"btn-group axis-menu\" data-id=\"").append(axisName).append("\">\n");
s.append(" <button type=\"button\" class=\"btn-sm btn-primary dropdown-toggle axis-btn\" data-toggle=\"dropdown\">");
s.append(" <span>").append(axisName).append("</span><span class=\"caret\"></span>");
s.append(" </button>\n");
s.append(" </div>\n");
s.append(" </th>\n");
long colspan = 1;
for (int j = i + 1; j < axisCount; j++)
{
colspan *= axes.get(j).size();
}
rowspan.put(axisName, colspan);
rowspanCounter.put(axisName, 0L);
columnCounter.put(axisName, 0L);
columns.put(axisName, axis.getColumns());
}
for (Column column : topColumns)
{
boolean isCmd = isColumnInlineExpression(column);
String colId = String.valueOf(column.getId());
s.append(" <th data-id=\"").append(colId).append("\" data-axis=\"").append(topAxisName).append("\" class=\"th-ncube-top ");
s.append(getColumnCssClass(topAxis, column));
s.append("\">");
if (isCmd)
{
s.append("<pre class=\"ncube-pre\">");
}
addColumnPrefixText(s, column);
s.append(column.toString());
if (isCmd)
{
s.append("</pre>");
}
s.append("</th>\n");
}
if (topAxis.size() != topColumnSize)
{
s.append(" <th class=\"th-ncube-top ");
s.append(getColumnCssClass(topAxis, topAxis.getDefaultColumn()));
s.append("\">Default</th>");
}
s.append("</tr>\n");
Map<String, Long> coord = new HashMap<>();
Map<String, Long> colIds = new HashMap<>();
// The left column headers and cells
for (long h = 0; h < height; h++)
{
s.append("<tr>\n");
// Column headers for the row
for (int i = 1; i < axisCount; i++)
{
Axis axis = axes.get(i);
String axisName = axis.getName();
Long count = rowspanCounter.get(axisName);
if (count == 0)
{
Long colIdx = columnCounter.get(axisName);
Column column = columns.get(axisName).get(colIdx.intValue());
coord.put(axisName, colIdx);
colIds.put(axisName, column.getId());
long span = rowspan.get(axisName);
String columnId = String.valueOf(column.getId());
String colCssClass = getColumnCssClass(axis, column);
if (span == 1)
{ // drop rowspan tag since rowspan="1" is redundant and wastes space in HTML
// Use column's ID as TH element's ID
s.append(" <th data-id=\"").append(columnId).append("\" data-axis=\"").append(axisName).append("\" class=\"th-ncube ");
s.append(colCssClass);
}
else
{ // Need to show rowspan attribute
// Use column's ID as TH element's ID
s.append(" <th data-id=\"").append(columnId).append("\" data-axis=\"").append(axisName).append("\" class=\"th-ncube ");
s.append(colCssClass);
s.append("\" rowspan=\"");
s.append(span);
}
s.append("\">");
boolean isCmd = isColumnInlineExpression(column);
if (isCmd)
{
s.append("<pre class=\"ncube-pre\">");
}
addColumnPrefixText(s, column);
s.append(column.toString());
if (isCmd)
{
s.append("</pre>");
}
s.append("</th>\n");
// Increment column counter
colIdx++;
if (colIdx >= axis.size())
{
colIdx = 0L;
}
columnCounter.put(axisName, colIdx);
}