All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.shell.table.TableBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.shell.table;

import static org.springframework.shell.table.BorderSpecification.FULL;
import static org.springframework.shell.table.BorderSpecification.INNER;
import static org.springframework.shell.table.BorderSpecification.INNER_VERTICAL;
import static org.springframework.shell.table.BorderSpecification.OUTLINE;
import static org.springframework.shell.table.SimpleHorizontalAligner.left;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

/**
 * A builder class to incrementally configure a Table.
 * @author Eric Bottard
 */
public class TableBuilder {

	private final TableModel model;

	private final Map formatters = new LinkedHashMap();

	private final Map sizeConstraints = new LinkedHashMap();

	private final Map wrappers = new LinkedHashMap();

	private final LinkedHashMap aligners = new LinkedHashMap();

	private final List borderSpecifications = new ArrayList();

	private final int rows;

	private final int columns;

	/**
	 * Construct a table with the given model. The table will use the following
	 * strategies for all cells, unless overridden:
    *
  • {@link DefaultFormatter default formatting} using {@literal toString()}
  • *
  • {@link AutoSizeConstraints sizing strategy} trying to use the maximum space, resorting to splitting lines on * spaces
  • *
  • {@link DelimiterTextWrapper wrapping text} on space characters
  • *
  • {@link SimpleHorizontalAligner left aligning} text.
  • *
* * @param model the data model of the table to construct */ public TableBuilder(TableModel model) { this.model = model; rows = model.getRowCount(); columns = model.getColumnCount(); formatters.put(CellMatchers.table(), new DefaultFormatter()); sizeConstraints.put(CellMatchers.table(), new AutoSizeConstraints()); wrappers.put(CellMatchers.table(), new DelimiterTextWrapper()); aligners.put(CellMatchers.table(), left); } private TableBuilder addBorder(int top, int left, int bottom, int right, int match, BorderStyle style) { Assert.isTrue(top >= 0 && top < rows, "top row must be positive and less than total number of rows"); Assert.isTrue(left >= 0 && left < columns, "left column must be positive and less than total number of columns"); Assert.isTrue(bottom > top && bottom <= rows, "bottom row must be greater than top and less than total number of rows"); Assert.isTrue(right >= left && right <= columns, "right column must be greater than left and less than total number of columns"); Assert.notNull(style, "style cannot be null"); borderSpecifications.add(new BorderSpecification(top, left, bottom, right, match, style)); return this; } public TableModel getModel() { return model; } public CellMatcherStub on(CellMatcher matcher) { return new CellMatcherStub(matcher); } public Table build() { return new Table(model, reverse(formatters), reverse(sizeConstraints), reverse(wrappers), aligners, borderSpecifications); } public BorderStub paintBorder(BorderStyle style, int match) { return new BorderStub(style, match); } // Convenience methods for borders /** * Set a border on the outline of the whole table. * @param style the style to apply * @return this, for method chaining */ public TableBuilder addOutlineBorder(BorderStyle style) { this.addBorder(0, 0, model.getRowCount(), model.getColumnCount(), OUTLINE, style); return this; } /** * Set a border on the outline of the whole table, as well as around the first row. * @param style the style to apply * @return this, for method chaining */ public TableBuilder addHeaderBorder(BorderStyle style) { this.addBorder(0, 0, 1, model.getColumnCount(), OUTLINE, style); return addOutlineBorder(style); } /** * Set a border around each and every cell of the table. * * @param style the style to apply * @return this, for method chaining */ public TableBuilder addFullBorder(BorderStyle style) { this.addBorder(0, 0, model.getRowCount(), model.getColumnCount(), FULL, style); return this; } /** * Set a border on the outline of the whole table, around the first row and draw vertical lines * around each column. * * @param style the style to apply * @return this, for method chaining */ public TableBuilder addHeaderAndVerticalsBorders(BorderStyle style) { this.addBorder(0, 0, 1, model.getColumnCount(), OUTLINE, style); this.addBorder(0, 0, model.getRowCount(), model.getColumnCount(), OUTLINE | INNER_VERTICAL, style); return this; } /** * Set a border on the inner verticals and horizontals of the table, but not on the outline. * * @param style the style to apply * @return this, for method chaining */ public TableBuilder addInnerBorder(BorderStyle style) { this.addBorder(0, 0, model.getRowCount(), model.getColumnCount(), INNER, style); return this; } private LinkedHashMap reverse(Map original) { LinkedHashMap result = new LinkedHashMap(original.size()); List> entries = new ArrayList>(original.entrySet()); for (int i = entries.size() - 1; i >= 0; i--) { Map.Entry entry = entries.get(i); result.put(entry.getKey(), entry.getValue()); } return result; } public class CellMatcherStub { private final CellMatcher cellMatcher; private CellMatcherStub(CellMatcher cellMatcher) { this.cellMatcher = cellMatcher; } public CellMatcherStub addFormatter(Formatter formatter) { formatters.put(this.cellMatcher, formatter); return this; } public CellMatcherStub addSizer(SizeConstraints sizer) { sizeConstraints.put(this.cellMatcher, sizer); return this; } public CellMatcherStub addWrapper(TextWrapper textWrapper) { wrappers.put(this.cellMatcher, textWrapper); return this; } public CellMatcherStub addAligner(Aligner aligner) { aligners.put(this.cellMatcher, aligner); return this; } public CellMatcherStub on(CellMatcher other) { return TableBuilder.this.on(other); } public TableBuilder and() { return TableBuilder.this; } public Table build() { return TableBuilder.this.build(); } } public class BorderStub { private final BorderStyle style; private final int match; private BorderStub(BorderStyle style, int match) { this.style = style; this.match = match; } public TopLeft fromRowColumn(int row, int column) { return new TopLeft(row, column); } public TopLeft fromTopLeft() { return new TopLeft(0, 0); } public class TopLeft { private final int row; private final int column; private TopLeft(int row, int column) { this.row = row; this.column = column; } public TableBuilder toRowColumn(int row, int column) { TableBuilder.this.addBorder(TopLeft.this.row, TopLeft.this.column, row, column, BorderStub.this.match, BorderStub.this.style); return TableBuilder.this; } public TableBuilder toBottomRight() { return toRowColumn(model.getRowCount(), model.getColumnCount()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy