fork download
  1. import java.time.LocalDate;
  2. import java.time.format.DateTimeFormatter;
  3. import java.time.format.ResolverStyle;
  4. import java.util.ArrayList;
  5. import java.util.Arrays;
  6. import java.util.Collection;
  7. import java.util.Iterator;
  8. import java.util.LinkedHashMap;
  9. import java.util.LinkedHashSet;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Set;
  13. import java.util.TreeSet;
  14. import java.util.function.Function;
  15.  
  16. class Tabela<L, C, X> {
  17. private final Set<C> colunas;
  18. private final Set<L> linhas;
  19. private final Map<L, Map<C, X>> celulas;
  20. private final Function<? super L, String> strLinhas;
  21. private final Function<? super C, String> strColunas;
  22. private final Function<? super X, String> strCelulas;
  23.  
  24. @FunctionalInterface
  25. public static interface TabelaConsumer<L, C, X> {
  26. public void accept(L linha, C coluna, X celula);
  27. }
  28.  
  29. public Tabela(
  30. Collection<L> linhas,
  31. Collection<C> colunas,
  32. Function<? super L, String> strLinhas,
  33. Function<? super C, String> strColunas,
  34. Function<? super X, String> strCelulas)
  35. {
  36. this.colunas = new LinkedHashSet<>(colunas);
  37. this.linhas = new LinkedHashSet<>(linhas);
  38. this.strLinhas = strLinhas;
  39. this.strColunas = strColunas;
  40. this.strCelulas = strCelulas;
  41. this.celulas = new LinkedHashMap<>(this.linhas.size());
  42. for (L linha : this.linhas) {
  43. Map<C, X> valoresLinha = new LinkedHashMap<>(this.colunas.size());
  44. for (C coluna : this.colunas) {
  45. valoresLinha.put(coluna, null);
  46. }
  47. this.celulas.put(linha, valoresLinha);
  48. }
  49. }
  50.  
  51. public void put(L linha, C coluna, X valor) {
  52. if (!linhas.contains(linha) || !colunas.contains(coluna)) throw new IllegalArgumentException();
  53. celulas.get(linha).put(coluna, valor);
  54. }
  55.  
  56. public X get(L linha, C coluna) {
  57. if (!linhas.contains(linha) || !colunas.contains(coluna)) return null;
  58. return celulas.get(linha).get(coluna);
  59. }
  60.  
  61. public void forEach(TabelaConsumer<? super L, ? super C, ? super X> consumer) {
  62. for (L linha : linhas) {
  63. for (C coluna : colunas) {
  64. consumer.accept(linha, coluna, get(linha, coluna));
  65. }
  66. }
  67. }
  68.  
  69. private List<Integer> calcularLargura() {
  70. List<Integer> lista = new ArrayList<>(colunas.size() + 1);
  71.  
  72. int m = 0;
  73. for (L linha : linhas) {
  74. int x = strLinhas.apply(linha).length();
  75. if (x > m) m = x;
  76. }
  77. lista.add(m);
  78.  
  79. for (C coluna : colunas) {
  80. int n = strColunas.apply(coluna).length();
  81. for (L linha : linhas) {
  82. X celula = get(linha, coluna);
  83. int x = celula == null ? 0 : strCelulas.apply(celula).length();
  84. if (x > n) n = x;
  85. }
  86. lista.add(n);
  87. }
  88.  
  89. return lista;
  90. }
  91.  
  92. private void imprimirSeparador(StringBuilder sb, int tamanho) {
  93. sb.append("+-");
  94. for (int i = 0; i <= tamanho; i++) {
  95. sb.append('-');
  96. }
  97. }
  98.  
  99. private void imprimirSeparador(StringBuilder sb, List<Integer> tamanhos) {
  100. for (int i : tamanhos) {
  101. imprimirSeparador(sb, i);
  102. }
  103. sb.append("+\n");
  104. }
  105.  
  106. private void imprimirCelula(StringBuilder sb, int tamanho, String conteudo) {
  107. sb.append("| ").append(conteudo);
  108. for (int i = conteudo.length(); i <= tamanho; i++) {
  109. sb.append(' ');
  110. }
  111. }
  112.  
  113. private void imprimirCabecalho(StringBuilder sb, List<Integer> tamanhos) {
  114. Iterator<Integer> it = tamanhos.iterator();
  115. imprimirCelula(sb, it.next(), "");
  116. for (C coluna : colunas) {
  117. imprimirCelula(sb, it.next(), strColunas.apply(coluna));
  118. }
  119. sb.append("|\n");
  120. }
  121.  
  122. private void imprimirLinha(StringBuilder sb, List<Integer> tamanhos, L linha) {
  123. Iterator<Integer> it = tamanhos.iterator();
  124. imprimirCelula(sb, it.next(), strLinhas.apply(linha));
  125. for (C coluna : colunas) {
  126. X celula = get(linha, coluna);
  127. imprimirCelula(sb, it.next(), celula == null ? "" : strCelulas.apply(celula));
  128. }
  129. sb.append("|\n");
  130. }
  131.  
  132. @Override
  133. public String toString() {
  134. List<Integer> tamanhos = calcularLargura();
  135. int larguraTotal = tamanhos.stream().reduce(0, Integer::sum) + 3 * tamanhos.size() + 2;
  136. StringBuilder sb = new StringBuilder(larguraTotal * (linhas.size() * 2 + 3));
  137. imprimirSeparador(sb, tamanhos);
  138. imprimirCabecalho(sb, tamanhos);
  139. imprimirSeparador(sb, tamanhos);
  140. for (L linha : linhas) {
  141. imprimirLinha(sb, tamanhos, linha);
  142. imprimirSeparador(sb, tamanhos);
  143. }
  144. return sb.toString();
  145. }
  146. }
  147.  
  148. class Local {
  149. private final String nome;
  150.  
  151. public Local(String nome) {
  152. this.nome = nome;
  153. }
  154.  
  155. @Override
  156. public String toString() {
  157. return nome;
  158. }
  159. }
  160.  
  161. class Atividade {
  162. private final String nome;
  163.  
  164. public Atividade(String nome) {
  165. this.nome = nome;
  166. }
  167.  
  168. @Override
  169. public String toString() {
  170. return nome;
  171. }
  172. }
  173.  
  174. class Teste {
  175.  
  176. private static final DateTimeFormatter FMT = DateTimeFormatter
  177. .ofPattern("dd/MM/uuuu")
  178. .withResolverStyle(ResolverStyle.STRICT);
  179.  
  180. public static void main(String[] args) {
  181.  
  182. // Define os locais e atividades.
  183. Local casa = new Local("Casa");
  184. Local escola = new Local("Escola");
  185. Local trabalho = new Local("Trabalho");
  186. Atividade estudo = new Atividade("Estudo");
  187. Atividade treino = new Atividade("Treino");
  188. Atividade apresentacao = new Atividade("Apresentação");
  189.  
  190. // Define a estrutura da tabela 1.
  191. Tabela<Atividade, Local, LocalDate> tabela1 = new Tabela<>(
  192. Arrays.asList(estudo, treino, apresentacao),
  193. Arrays.asList(casa, escola, trabalho),
  194. Object::toString,
  195. Object::toString,
  196. ld -> ld.format(FMT)
  197. );
  198.  
  199. // Preenche a tabela 1.
  200. tabela1.put(estudo, casa, LocalDate.of(2017, 2, 1));
  201. tabela1.put(estudo, escola, LocalDate.of(2017, 3, 10));
  202. tabela1.put(estudo, trabalho, LocalDate.of(2017, 1, 1));
  203. tabela1.put(treino, casa, LocalDate.of(2017, 5, 3));
  204. tabela1.put(treino, escola, LocalDate.of(2017, 2, 4));
  205. tabela1.put(treino, trabalho, LocalDate.of(2017, 5, 1));
  206. tabela1.put(apresentacao, casa, LocalDate.of(2017, 2, 2));
  207. tabela1.put(apresentacao, escola, LocalDate.of(2017, 3, 3));
  208. tabela1.put(apresentacao, trabalho, LocalDate.of(2017, 12, 10));
  209.  
  210. // Mostra a tabela 1.
  211. System.out.println("Tabela 1:");
  212. System.out.println(tabela1);
  213.  
  214. // Descobre as datas que são linhas da tabela 2.
  215. Set<LocalDate> datas = new TreeSet<>();
  216. tabela1.forEach((atividade, local, data) -> datas.add(data));
  217.  
  218. // Define a estrutura da tabela 2.
  219. Tabela<LocalDate, Atividade, Local> tabela2 = new Tabela<>(
  220. datas,
  221. Arrays.asList(estudo, treino, apresentacao),
  222. ld -> ld.format(FMT),
  223. Object::toString,
  224. Object::toString
  225. );
  226.  
  227. // Preenche a tabela 2 com base nos dados da tabela 1.
  228. tabela1.forEach((atividade, local, data) -> tabela2.put(data, atividade, local));
  229.  
  230. // Mostra a tabela 2.
  231. System.out.println("Tabela 2:");
  232. System.out.println(tabela2);
  233. }
  234. }
Success #stdin #stdout 0.14s 4386816KB
stdin
Standard input is empty
stdout
Tabela 1:
+--------------+------------+------------+------------+
|              | Casa       | Escola     | Trabalho   |
+--------------+------------+------------+------------+
| Estudo       | 01/02/2017 | 10/03/2017 | 01/01/2017 |
+--------------+------------+------------+------------+
| Treino       | 03/05/2017 | 04/02/2017 | 01/05/2017 |
+--------------+------------+------------+------------+
| Apresentação | 02/02/2017 | 03/03/2017 | 10/12/2017 |
+--------------+------------+------------+------------+

Tabela 2:
+------------+----------+----------+--------------+
|            | Estudo   | Treino   | Apresentação |
+------------+----------+----------+--------------+
| 01/01/2017 | Trabalho |          |              |
+------------+----------+----------+--------------+
| 01/02/2017 | Casa     |          |              |
+------------+----------+----------+--------------+
| 02/02/2017 |          |          | Casa         |
+------------+----------+----------+--------------+
| 04/02/2017 |          | Escola   |              |
+------------+----------+----------+--------------+
| 03/03/2017 |          |          | Escola       |
+------------+----------+----------+--------------+
| 10/03/2017 | Escola   |          |              |
+------------+----------+----------+--------------+
| 01/05/2017 |          | Trabalho |              |
+------------+----------+----------+--------------+
| 03/05/2017 |          | Casa     |              |
+------------+----------+----------+--------------+
| 10/12/2017 |          |          | Trabalho     |
+------------+----------+----------+--------------+