OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 65 | Rev 93 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.sql.model;
15
 
16
import org.openconcerto.utils.Tuple2;
17
 
18
import java.sql.ResultSet;
19
import java.sql.SQLException;
20
import java.util.ArrayList;
83 ilm 21
import java.util.Collections;
17 ilm 22
import java.util.List;
23
 
24
import org.apache.commons.dbutils.ResultSetHandler;
25
 
26
public final class SQLRowListRSH implements ResultSetHandler {
27
 
63 ilm 28
    // hashCode()/equals() needed for data source cache
83 ilm 29
    public static final class RSH implements ResultSetHandler {
63 ilm 30
        private final Tuple2<SQLTable, List<String>> names;
31
 
83 ilm 32
        // allow to create rows from arbitrary columns (and not just directly from actual fields of
33
        // the same table)
34
        // ATTN doesn't check that the types of columns are coherent with the types of the fields
35
        public RSH(final SQLTable t, final List<String> names) {
36
            this(Tuple2.create(t, names));
37
            if (!t.getFieldsName().containsAll(names))
38
                throw new IllegalArgumentException("Not all names are fields of " + t + " : " + names);
39
        }
40
 
63 ilm 41
        private RSH(Tuple2<SQLTable, List<String>> names) {
42
            this.names = names;
43
        }
44
 
45
        @Override
46
        public List<SQLRow> handle(ResultSet rs) throws SQLException {
83 ilm 47
            // since the result will be cached, disallow its modification (e.g.avoid
48
            // ConcurrentModificationException)
49
            return Collections.unmodifiableList(SQLRow.createListFromRS(this.names.get0(), rs, this.names.get1()));
63 ilm 50
        }
51
 
52
        @Override
53
        public int hashCode() {
54
            return this.names.hashCode();
55
        }
56
 
57
        @Override
58
        public boolean equals(Object obj) {
59
            if (this == obj)
60
                return true;
61
            if (obj == null)
62
                return false;
63
            if (getClass() != obj.getClass())
64
                return false;
65
            final RSH other = (RSH) obj;
66
            return this.names.equals(other.names);
67
        }
68
    }
69
 
83 ilm 70
    private static TableRef checkTable(final TableRef t) {
71
        if (t == null)
72
            throw new IllegalArgumentException("null table");
73
        if (!t.getTable().isRowable())
74
            throw new IllegalArgumentException("table isn't rowable : " + t);
75
        return t;
76
    }
77
 
78
    private static Tuple2<SQLTable, List<String>> getIndexes(SQLSelect sel, final TableRef passedTable, final boolean findTable) {
79
        final List<FieldRef> selectFields = sel.getSelectFields();
17 ilm 80
        final int size = selectFields.size();
81
        if (size == 0)
82
            throw new IllegalArgumentException("empty select : " + sel);
83 ilm 83
        TableRef t;
17 ilm 84
        if (findTable) {
85
            if (passedTable != null)
86
                throw new IllegalArgumentException("non null table " + passedTable);
83 ilm 87
            t = null;
17 ilm 88
        } else {
83 ilm 89
            t = checkTable(passedTable);
17 ilm 90
        }
91
        final List<String> l = new ArrayList<String>(size);
92
        for (int i = 0; i < size; i++) {
83 ilm 93
            final FieldRef field = selectFields.get(i);
94
            if (field == null) {
95
                // computed field
17 ilm 96
                l.add(null);
83 ilm 97
            } else {
98
                if (t == null) {
99
                    assert findTable;
100
                    t = checkTable(field.getTableRef());
101
                }
102
                assert t != null && t.getTable().isRowable();
103
 
104
                if (field.getTableRef().equals(t)) {
105
                    l.add(field.getField().getName());
106
                } else if (findTable) {
107
                    // prevent ambiguity : either specify a table or there must be only one table
108
                    throw new IllegalArgumentException(field + " is not in " + t);
109
                } else {
110
                    l.add(null);
111
                }
112
            }
17 ilm 113
        }
83 ilm 114
        return Tuple2.create(t.getTable(), l);
17 ilm 115
    }
116
 
117
    /**
118
     * Create a handler that don't need metadata.
119
     *
120
     * @param sel the select that will produce the result set, must only have one table.
121
     * @return a handler creating a list of {@link SQLRow}.
122
     */
123
    static public ResultSetHandler createFromSelect(final SQLSelect sel) {
124
        return create(getIndexes(sel, null, true));
125
    }
126
 
127
    /**
128
     * Create a handler that don't need metadata. Useful since some JDBC drivers perform queries for
129
     * each metadata.
130
     *
131
     * @param sel the select that will produce the result set.
83 ilm 132
     * @param t the table for which to create rows.
17 ilm 133
     * @return a handler creating a list of {@link SQLRow}.
134
     */
83 ilm 135
    static public ResultSetHandler createFromSelect(final SQLSelect sel, final TableRef t) {
17 ilm 136
        return create(getIndexes(sel, t, false));
137
    }
138
 
139
    static private ResultSetHandler create(final Tuple2<SQLTable, List<String>> names) {
63 ilm 140
        return new RSH(names);
17 ilm 141
    }
142
 
143
    @SuppressWarnings("unchecked")
144
    static public List<SQLRow> execute(final SQLSelect sel) {
145
        final Tuple2<SQLTable, List<String>> indexes = getIndexes(sel, null, true);
146
        return (List<SQLRow>) indexes.get0().getDBSystemRoot().getDataSource().execute(sel.asString(), create(indexes));
147
    }
148
 
149
    private final SQLTable t;
150
    private final boolean tableOnly;
151
 
152
    public SQLRowListRSH(SQLTable t) {
153
        this(t, false);
154
    }
155
 
156
    public SQLRowListRSH(SQLTable t, final boolean tableOnly) {
157
        super();
158
        this.t = t;
159
        this.tableOnly = tableOnly;
160
    }
161
 
162
    public Object handle(ResultSet rs) throws SQLException {
163
        return SQLRow.createListFromRS(this.t, rs, this.tableOnly);
164
    }
165
}