OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 17 | Rev 20 | 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.request;
15
 
16
import org.openconcerto.sql.FieldExpander;
17
import org.openconcerto.sql.model.SQLField;
18
import org.openconcerto.sql.model.SQLRowValues;
19
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
20
import org.openconcerto.sql.model.SQLSelect;
21
import org.openconcerto.sql.model.SQLTable;
22
import org.openconcerto.sql.model.Where;
23
import org.openconcerto.sql.model.graph.Path;
24
import org.openconcerto.utils.cc.ITransformer;
25
 
26
import java.beans.PropertyChangeListener;
27
import java.beans.PropertyChangeSupport;
28
import java.util.Collection;
29
import java.util.Collections;
30
import java.util.List;
31
 
32
public abstract class BaseFillSQLRequest extends BaseSQLRequest {
33
 
34
    /**
35
     * Whether to use "FOR SHARE" in list requests (preventing roles with just SELECT right from
36
     * seeing the list).
37
     */
38
    public static final boolean lockSelect = !Boolean.getBoolean("org.openconcerto.sql.noSelectLock");
39
 
40
    private final SQLTable primaryTable;
41
    private Where where;
42
    private ITransformer<SQLSelect, SQLSelect> selTransf;
43
 
44
    private SQLRowValues graph;
45
    private SQLRowValues graphToFetch;
46
 
47
    private final PropertyChangeSupport supp = new PropertyChangeSupport(this);
48
 
49
    public BaseFillSQLRequest(final SQLTable primaryTable, Where w) {
50
        super();
51
        if (primaryTable == null)
52
            throw new NullPointerException();
53
        this.primaryTable = primaryTable;
54
        this.where = w;
55
        this.selTransf = null;
56
        this.graph = null;
57
        this.graphToFetch = null;
58
    }
59
 
60
    public BaseFillSQLRequest(BaseFillSQLRequest req) {
61
        super();
62
        this.primaryTable = req.getPrimaryTable();
63
        this.where = req.where;
64
        this.selTransf = req.selTransf;
65
        // TODO copy
66
        // use methods since they're both lazy
67
        this.graph = req.getGraph();
68
        this.graphToFetch = req.getGraphToFetch();
69
    }
70
 
71
    private final SQLRowValues computeGraph() {
72
        if (this.getFields() == null)
73
            return null;
74
 
75
        final SQLRowValues vals = new SQLRowValues(this.getPrimaryTable());
76
        for (final SQLField f : this.getFields()) {
77
            vals.put(f.getName(), null);
78
        }
79
        // keep order field in graph (not only in graphToFetch) so that a debug column is created
80
        for (final Path orderP : this.getOrder()) {
81
            final SQLRowValues orderVals = vals.followPath(orderP);
82
            if (orderVals != null && orderVals.getTable().isOrdered()) {
83
                orderVals.put(orderVals.getTable().getOrderField().getName(), null);
84
            }
85
        }
86
        this.getShowAs().expand(vals);
87
        return vals;
88
    }
89
 
90
    /**
91
     * The graph computed by expanding {@link #getFields()} by {@link #getShowAs()}.
92
     *
93
     * @return the expanded graph.
94
     */
95
    public final SQLRowValues getGraph() {
96
        if (this.graph == null)
97
            this.graph = this.computeGraph();
98
        return this.graph;
99
    }
100
 
101
    /**
102
     * The graph to fetch, should be a superset of {@link #getGraph()}.
103
     *
104
     * @return the graph to fetch.
105
     */
106
    public final SQLRowValues getGraphToFetch() {
107
        if (this.graphToFetch == null && this.getGraph() != null) {
108
            this.graphToFetch = this.getGraph().deepCopy();
109
            this.customizeToFetch(this.graphToFetch);
110
        }
111
        return this.graphToFetch;
112
    }
113
 
114
    protected void customizeToFetch(SQLRowValues graphToFetch) {
115
    }
116
 
117
    protected final SQLRowValuesListFetcher getFetcher(final Where w) {
118
        final String tableName = getPrimaryTable().getName();
119
        final SQLRowValuesListFetcher fetcher = new SQLRowValuesListFetcher(getGraphToFetch(), true);
19 ilm 120
        // include rows having NULL (not undefined ID) foreign keys
121
        fetcher.setFullOnly(false);
122
        // treat the same way tables with or without undefined ID
123
        fetcher.setIncludeForeignUndef(false);
17 ilm 124
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
125
            @Override
126
            public SQLSelect transformChecked(SQLSelect sel) {
127
                sel = transformSelect(sel);
128
                if (lockSelect)
129
                    sel.addWaitPreviousWriteTXTable(tableName);
130
                for (final Path orderP : getOrder()) {
131
                    sel.addOrderSilent(sel.assurePath(getPrimaryTable().getName(), orderP));
132
                }
133
                return sel.andWhere(getWhere()).andWhere(w);
134
            }
135
        });
136
        return fetcher;
137
    }
138
 
139
    protected List<Path> getOrder() {
140
        return Collections.singletonList(new Path(getPrimaryTable()));
141
    }
142
 
143
    public final void setWhere(Where w) {
144
        this.where = w;
145
        fireWhereChange();
146
    }
147
 
148
    public final Where getWhere() {
149
        return this.where;
150
    }
151
 
152
    public final Collection<SQLField> getAllFields() {
153
        // don't rely on the expansion of our fields, since our fetcher can be arbitrary modified
154
        // (eg by adding a where on a field of a non-displayed table)
155
        return this.getFetcher(null).getReq().getFields();
156
    }
157
 
158
    protected abstract Collection<SQLField> getFields();
159
 
160
    protected SQLSelect transformSelect(SQLSelect sel) {
161
        return this.selTransf == null ? sel : this.selTransf.transformChecked(sel);
162
    }
163
 
164
    public final ITransformer<SQLSelect, SQLSelect> getSelectTransf() {
165
        return this.selTransf;
166
    }
167
 
168
    /**
169
     * Allows to transform the SQLSelect returned by getFillRequest().
170
     *
171
     * @param transf the transformer to apply.
172
     */
173
    public final void setSelectTransf(ITransformer<SQLSelect, SQLSelect> transf) {
174
        this.selTransf = transf;
175
        this.fireWhereChange();
176
    }
177
 
178
    protected abstract FieldExpander getShowAs();
179
 
180
    public final SQLTable getPrimaryTable() {
181
        return this.primaryTable;
182
    }
183
 
184
    protected final void fireWhereChange() {
185
        this.supp.firePropertyChange("where", null, null);
186
    }
187
 
188
    public final void addWhereListener(PropertyChangeListener l) {
189
        this.supp.addPropertyChangeListener("where", l);
190
    }
191
 
192
    public final void rmWhereListener(PropertyChangeListener l) {
193
        this.supp.removePropertyChangeListener("where", l);
194
    }
195
 
196
    public String toString() {
197
        return this.getClass().getName() + " on " + this.getPrimaryTable();
198
    }
199
}