View Javadoc
1   /*
2    * Tentackle - https://tentackle.org.
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17   */
18  
19  package org.tentackle.dbms;
20  
21  import org.tentackle.session.PersistenceException;
22  
23  import java.sql.ResultSetMetaData;
24  import java.sql.SQLException;
25  import java.util.HashMap;
26  import java.util.Locale;
27  import java.util.Map;
28  
29  /**
30   * A subset of the columns returned by a {@link ResultSetWrapper}.
31   *
32   * @author harald
33   */
34  public class ResultSetSkipBlock {
35  
36    private final ResultSetWrapper rs;                  // the rs wrapper
37    private final int skippedColumns;                   // number of columns skipped
38    private final Map<String,Integer> columnMap;        // the current map of columns
39    private int maxColumnIndex;                         // the highest used column index so far
40  
41    /**
42     * Creates a skip block.
43     *
44     * @param rs the result set
45     * @param skippedColumns the number of columns skipped
46     */
47    public ResultSetSkipBlock(ResultSetWrapper rs, int skippedColumns) {
48      this.rs = rs;
49      this.skippedColumns = skippedColumns;
50      this.maxColumnIndex = skippedColumns;
51      // build the column map
52      columnMap = new HashMap<>();
53      int max = rs.getColumnCount();
54      ResultSetMetaData meta = rs.getMetaData();
55      for (int i = skippedColumns + 1; i <= max; i++) {
56        try {
57          // append only the first occurrence (from the left).
58          // lowercase because column names are converted to lowercase in the model (see AttributeImpl)
59          columnMap.putIfAbsent(meta.getColumnName(i).toLowerCase(Locale.ROOT), i);
60        }
61        catch (SQLException e) {
62          throw new PersistenceException(rs.getSession(), e);
63        }
64      }
65    }
66  
67    /**
68     * Gets the number of columns skipped in the result set.
69     *
70     * @return the number of skipped columns, 0 if no column skipped
71     */
72    public int getSkippedColumns() {
73      return skippedColumns;
74    }
75  
76    /**
77     * Gets the highest used column index.<br>
78     * This will be the skippedColumns of the next skip block.
79     *
80     * @return the highest-used index
81     */
82    public int getMaxColumnIndex() {
83      return maxColumnIndex;
84    }
85  
86    /**
87     * Maps the given column name to its column index.
88     * <p>
89     * Finds the first column with that name after the skipped columns of this block.
90     * The column names of the result set are mapped in lowercase.
91     *
92     * @param name the column name
93     * @return the index in the result set
94     * @throws PersistenceException if no such column beyond the skipped columns
95     */
96    public int findColumn(String name) {
97      Integer ndx = columnMap.get(name);
98      if (ndx == null) {
99        throw new PersistenceException(rs.getSession(),
100               "no such column '" + name + "' beyond " + skippedColumns + " skipped columns in " + rs);
101     }
102     applyColumnIndex(ndx);
103     return ndx;
104   }
105 
106   /**
107    * Applies the used column index to this skip block.
108    *
109    * @param ndx the used column index
110    */
111   public void applyColumnIndex(int ndx) {
112     if (ndx > maxColumnIndex) {   // remember the highest configured column
113       maxColumnIndex = ndx;
114     }
115   }
116 
117 }