View Javadoc
1   /*
2    * CSVeed (https://github.com/42BV/CSVeed)
3    *
4    * Copyright 2013-2023 CSVeed.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of The Apache Software License,
8    * Version 2.0 which accompanies this distribution, and is available at
9    * https://www.apache.org/licenses/LICENSE-2.0.txt
10   */
11  package org.csveed.bean;
12  
13  import org.csveed.common.Column;
14  
15  /**
16   * <p>
17   * The concept of dynamic columns comes into play when a sheet contains columns that are not really part of the columns,
18   * but should have been separate rows. For example, let's say you have a table that looks like this:
19   * </p>
20   * <code>
21   *     | name   | town   | jan 14 | jan 15 | jan 16 |
22   *     | Rob    | Leiden |   4    |   1    |   7    |
23   *     | Rob    | Delft  |   0    |   3    |   8    |
24   *     | Erik   | Leiden |   2    |   4    |   1    |
25   *     | Erik   | Sneek  |   1    |   0    |   9    |
26   * </code>
27   * <p>
28   * Let's say you want to compact this table into the following, normalized format: <code>
29   *     | name   | town   | date   | visits |
30   *     | Rob    | Leiden | jan 14 |   4    |
31   *     | Rob    | Leiden | jan 15 |   1    |
32   *     | Rob    | Leiden | jan 16 |   7    |
33   *     | Rob    | Delft  | jan 14 |   0    |
34   *     | Rob    | Delft  | jan 15 |   3    |
35   *     | Rob    | Delft  | jan 16 |   8    |
36   *     | Erik   | Leiden | jan 14 |   2    |
37   *     | Erik   | Leiden | jan 15 |   4    |
38   *     | Erik   | Leiden | jan 16 |   1    |
39   *     | Erik   | Sneek  | jan 14 |   1    |
40   *     | Erik   | Sneek  | jan 15 |   0    |
41   *     | Erik   | Sneek  | jan 16 |   9    |
42   * </code>
43   * <p>
44   * In order to realize this goal, you need to make that startIndexDynamicColumns is set to 3 on @CsvFile. This will
45   * assume the columns starting with the third and all thereafter are dynamic. For every dynamic column, a new bean will
46   * be created. All static columns will be copied into every created bean.
47   * </p>
48   * <p>
49   * The header name and the cell value can be copied into bean properties. In the example, the bean requires two fields
50   * date and visits. date must be annotated with @CsvHeaderName and visits with @CsvHeaderValue.
51   * </p>
52   */
53  public class DynamicColumn {
54  
55      /** The start column. */
56      private Column startColumn;
57  
58      /** The current column. */
59      private Column currentColumn;
60  
61      /**
62       * Instantiates a new dynamic column.
63       *
64       * @param configuredStartColumn
65       *            the configured start column
66       */
67      public DynamicColumn(Column configuredStartColumn) {
68          this.startColumn = configuredStartColumn == null ? null : new Column(configuredStartColumn);
69          this.currentColumn = configuredStartColumn == null ? null : new Column(configuredStartColumn);
70      }
71  
72      /**
73       * Check for reset.
74       *
75       * @param numberOfColumns
76       *            the number of columns
77       */
78      public void checkForReset(int numberOfColumns) {
79          if (lastDynamicColumnPassed(numberOfColumns)) {
80              reset();
81          }
82      }
83  
84      /**
85       * Reset.
86       */
87      protected void reset() {
88          this.currentColumn = new Column(this.startColumn);
89      }
90  
91      /**
92       * Last dynamic column passed.
93       *
94       * @param numberOfColumns
95       *            the number of columns
96       *
97       * @return true, if successful
98       */
99      protected boolean lastDynamicColumnPassed(int numberOfColumns) {
100         return this.currentColumn != null && this.currentColumn.getColumnIndex() > numberOfColumns;
101     }
102 
103     /**
104      * At first dynamic column.
105      *
106      * @return true, if successful
107      */
108     public boolean atFirstDynamicColumn() {
109         return this.startColumn == null || this.startColumn.equals(this.currentColumn);
110     }
111 
112     /**
113      * Advance dynamic column.
114      */
115     public void advanceDynamicColumn() {
116         if (currentColumn == null) {
117             return;
118         }
119         this.currentColumn = currentColumn.nextColumn();
120     }
121 
122     /**
123      * Checks if is dynamic column active.
124      *
125      * @param currentColumn
126      *            the current column
127      *
128      * @return true, if is dynamic column active
129      */
130     public boolean isDynamicColumnActive(Column currentColumn) {
131         return this.currentColumn != null && this.currentColumn.getColumnIndex() == currentColumn.getColumnIndex();
132     }
133 
134 }