OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
132 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.ui.light;
15
 
16
import org.openconcerto.sql.Configuration;
174 ilm 17
import org.openconcerto.sql.model.FieldPath;
18
import org.openconcerto.sql.model.FieldRef;
19
import org.openconcerto.sql.model.SQLFunctionField;
20
import org.openconcerto.sql.model.SQLFunctionField.SQLFunction;
132 ilm 21
import org.openconcerto.sql.model.SQLRowAccessor;
174 ilm 22
import org.openconcerto.sql.model.SQLRowValues;
142 ilm 23
import org.openconcerto.sql.model.SQLSelect;
174 ilm 24
import org.openconcerto.sql.model.Where;
142 ilm 25
import org.openconcerto.sql.view.list.ITableModel;
26
import org.openconcerto.sql.view.list.ListSQLLine;
132 ilm 27
import org.openconcerto.sql.view.list.SQLTableModelColumn;
28
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
142 ilm 29
import org.openconcerto.ui.SwingThreadUtils;
30
import org.openconcerto.ui.light.ColumnSpec;
31
import org.openconcerto.ui.light.ColumnsSpec;
132 ilm 32
import org.openconcerto.ui.light.LightUIElement;
33
import org.openconcerto.ui.light.LightUITable;
34
import org.openconcerto.ui.light.Row;
174 ilm 35
import org.openconcerto.ui.light.TableSearchParameter;
36
import org.openconcerto.ui.light.TableSearchParameterType;
37
import org.openconcerto.ui.light.UserSearch;
38
import org.openconcerto.ui.light.UserSearchItem;
142 ilm 39
import org.openconcerto.utils.NumberUtils;
40
import org.openconcerto.utils.cc.ITransformer;
132 ilm 41
 
42
import java.util.ArrayList;
174 ilm 43
import java.util.Collections;
44
import java.util.HashMap;
45
import java.util.HashSet;
132 ilm 46
import java.util.List;
174 ilm 47
import java.util.Locale;
48
import java.util.Map;
49
import java.util.Set;
142 ilm 50
import java.util.concurrent.Callable;
132 ilm 51
 
142 ilm 52
import javax.swing.SwingUtilities;
53
import javax.swing.event.TableModelListener;
54
 
55
import org.jdom2.Document;
56
import org.jdom2.Element;
57
import org.jdom2.input.DOMBuilder;
58
 
132 ilm 59
import net.minidev.json.JSONObject;
60
 
142 ilm 61
public abstract class LightRowValuesTable extends LightUITable {
132 ilm 62
 
142 ilm 63
    public static final int MAX_LINE_TO_SEND = 100;
132 ilm 64
 
142 ilm 65
    private int totalRowCount = -1;
66
 
67
    private int offset = 0;
68
 
156 ilm 69
    private transient ITableModel model;
142 ilm 70
 
156 ilm 71
    private transient ITransformer<SQLSelect, SQLSelect> orginTransformer;
142 ilm 72
 
174 ilm 73
    private transient List<TableModelListener> tableModelListeners = new ArrayList<>();
142 ilm 74
 
174 ilm 75
    private Map<TableSearchParameter, TableSearchMatcher> searchMap = new HashMap<>();
76
 
156 ilm 77
    public LightRowValuesTable() {
78
        // Serialization
79
    }
80
 
142 ilm 81
    public LightRowValuesTable(final Configuration configuration, final Number userId, final String id, final ITableModel model) {
82
        super(id);
83
 
84
        this.model = model;
85
        final ColumnsSpec columnsSpec = this.createColumnsSpecFromModelSource(configuration, userId);
86
 
87
        this.getTableSpec().setColumns(columnsSpec);
88
 
89
        if (model.getReq() instanceof SQLTableModelSourceOnline) {
90
            final SQLTableModelSourceOnline source = (SQLTableModelSourceOnline) model.getReq();
91
            this.orginTransformer = source.getReq().getSelectTransf();
174 ilm 92
 
93
            List<SQLTableModelColumn> columns = model.getReq().getColumns();
94
            // all
95
            // TODO : traduire
96
            TableSearchParameter tableSearchParameterAll = new TableSearchParameter("all", "Tous");
97
 
98
            TableSearchMatcher m = new TableSearchMatcher() {
99
 
100
                @Override
101
                public boolean useMatch() {
102
                    return false;
103
                }
104
 
105
                @Override
106
                public boolean match(SQLRowValues r, TableSearchParameterType type, String txt) {
107
                    return true;
108
                }
109
 
110
                @Override
111
                public Where getWhere(SQLSelect sel, TableSearchParameterType type, String txt) {
112
                    final Set<FieldPath> fields = new HashSet<>();
113
                    for (SQLTableModelColumn col : columns) {
114
                        fields.addAll(col.getPaths());
115
                    }
116
                    final List<Where> wFields = new ArrayList<>(fields.size());
117
                    for (final FieldPath fpath : fields) {
118
                        if (fpath.getField().getType().getJavaType().equals(String.class)) {
119
                            final FieldRef fieldRef = sel.followFieldPath(fpath);
120
                            if (type.getType().equals(UserSearchItem.TYPE_CONTAINS)) {
121
                                final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", "%" + txt.toLowerCase() + "%");
122
                                wFields.add(w);
123
                            }
124
                            if (type.getType().equals(UserSearchItem.TYPE_STARTS_WITH)) {
125
                                final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase() + "%");
126
                                wFields.add(w);
127
                            }
128
                            if (type.getType().equals(UserSearchItem.TYPE_IS)) {
129
                                final Where w = new Where(new SQLFunctionField(SQLFunction.LOWER, fieldRef), "LIKE", txt.toLowerCase());
130
                                wFields.add(w);
131
                            }
132
                        }
133
                    }
134
                    return Where.or(wFields);
135
                }
136
 
137
                @Override
138
                public List<FieldPath> getAdditionnalFieldsToFetch() {
139
                    return Collections.emptyList();
140
                }
141
            };
142
            tableSearchParameterAll.add(TableSearchParameterType.getContainsStringInstance(Locale.FRENCH));
143
            tableSearchParameterAll.add(TableSearchParameterType.getIsStringInstance(Locale.FRENCH));
144
 
145
            this.addSearchParameter(tableSearchParameterAll, m);
146
 
147
            //
148
            for (int i = 0; i < columns.size(); i++) {
149
                SQLTableModelColumn col = columns.get(i);
150
                TableSearchParameter tableSearchParameter = new TableSearchParameter("col" + i, col.getName());
151
                // FIXME : locale à recuperer depuis le user
152
                // TODO : mettre d'autres TableSearchParameterType en fonction du type de la colonne
153
                tableSearchParameter.add(TableSearchParameterType.getContainsStringInstance(Locale.FRENCH));
154
                tableSearchParameter.add(TableSearchParameterType.getIsStringInstance(Locale.FRENCH));
155
 
156
                TableSearchMatcher tableSearchMatcher = new TableSearchColumnMatcher(col);
157
                this.addSearchParameter(tableSearchParameter, tableSearchMatcher);
158
            }
159
 
142 ilm 160
        } else {
161
            this.orginTransformer = null;
162
        }
163
 
164
        this.setDynamicLoad(true);
132 ilm 165
    }
166
 
167
    // Clone constructor
168
    public LightRowValuesTable(final LightRowValuesTable tableElement) {
169
        super(tableElement);
142 ilm 170
 
171
        this.model = tableElement.model;
172
        this.totalRowCount = tableElement.totalRowCount;
173
        this.orginTransformer = tableElement.orginTransformer;
132 ilm 174
    }
175
 
142 ilm 176
    // Json constructor
177
    public LightRowValuesTable(final JSONObject json) {
178
        super(json);
179
        this.orginTransformer = null;
132 ilm 180
    }
181
 
142 ilm 182
    public final int getTotalRowsCount() {
183
        return this.totalRowCount;
132 ilm 184
    }
185
 
142 ilm 186
    public final int getOffset() {
187
        return this.offset;
132 ilm 188
    }
189
 
142 ilm 190
    public final void setOffset(final int offset) {
191
        this.offset = offset;
132 ilm 192
    }
193
 
142 ilm 194
    public final void addTableModelListener(final TableModelListener tableModelListener) {
195
        this.tableModelListeners.add(tableModelListener);
174 ilm 196
        SwingUtilities.invokeLater(new Runnable() {
197
            @Override
198
            public void run() {
199
                LightRowValuesTable.this.model.addTableModelListener(tableModelListener);
200
            }
201
        });
202
 
132 ilm 203
    }
204
 
142 ilm 205
    public final void removeTableModelListener(final TableModelListener tableModelListener) {
206
        this.tableModelListeners.remove(tableModelListener);
207
        this.model.removeTableModelListener(tableModelListener);
132 ilm 208
    }
209
 
142 ilm 210
    public ITableModel getModel() {
211
        return this.model;
212
    }
132 ilm 213
 
142 ilm 214
    public final LightListSqlRow getRowFromSqlID(final Number sqlID) {
215
        if (this.hasRow()) {
216
            final int size = this.getTableSpec().getContent().getRowsCount();
217
            for (int i = 0; i < size; i++) {
218
                final LightListSqlRow row = (LightListSqlRow) this.getRow(i);
219
                if (NumberUtils.areNumericallyEqual(row.getSqlRow().getIDNumber(), sqlID)) {
220
                    return row;
221
                }
222
            }
223
        }
224
        return null;
132 ilm 225
    }
226
 
142 ilm 227
    public final LightListSqlRow createLightListRowFromListLine(final ListSQLLine listSqlLine, final int index) throws IllegalStateException {
228
        final ColumnsSpec columnsSpec = this.getTableSpec().getColumns();
229
        final List<SQLTableModelColumn> sqlColumns = this.getModelColumns();
230
        final int colSize = sqlColumns.size();
132 ilm 231
 
142 ilm 232
        final LightListSqlRow row = new LightListSqlRow(listSqlLine.getRow(), listSqlLine.getID());
233
        final List<Object> values = new ArrayList<Object>();
234
        for (int i = 0; i < colSize; i++) {
235
            final String columnId = columnsSpec.getColumn(i).getId();
236
            final SQLTableModelColumn col = getColumnFromId(sqlColumns, columnId);
132 ilm 237
 
142 ilm 238
            if (col != null) {
239
                Object value = col.show(row.getSqlRow());
240
                if (col.getLightUIrenderer() != null) {
241
                    value = col.getLightUIrenderer().getLightUIElement(value, 0, i);
242
                }
243
                values.add(value);
244
            } else {
245
                throw new IllegalArgumentException("column " + columnId + " is in ColumnsSpec but it is not found in SQLTableModelColumn");
132 ilm 246
            }
247
        }
142 ilm 248
        row.setValues(values);
249
 
250
        return row;
132 ilm 251
    }
252
 
142 ilm 253
    public final SQLRowAccessor getFirstSelectedSqlRow() {
254
        final List<Row> selectedRows = this.getSelectedRows();
255
        if (selectedRows.isEmpty()) {
256
            return null;
257
        } else {
258
            return ((LightListSqlRow) selectedRows.get(0)).getSqlRow();
259
        }
132 ilm 260
    }
261
 
142 ilm 262
    private final List<SQLTableModelColumn> getModelColumns() {
263
        try {
264
            // TODO: clean swing
265
            return SwingThreadUtils.call(new Callable<List<SQLTableModelColumn>>() {
266
                @Override
267
                public List<SQLTableModelColumn> call() throws Exception {
268
                    return LightRowValuesTable.this.getModel().getReq().getColumns();
269
                }
270
            });
271
        } catch (final Exception ex) {
272
            throw new IllegalStateException(ex);
273
        }
132 ilm 274
    }
142 ilm 275
 
276
    private final SQLTableModelColumn getColumnFromId(final List<SQLTableModelColumn> allCols, final String columnId) {
277
        final int columnSize = allCols.size();
278
        for (int i = 0; i < columnSize; i++) {
279
            final SQLTableModelColumn tableModelColumn = allCols.get(i);
280
            if (tableModelColumn.getIdentifier().equals(columnId)) {
281
                return tableModelColumn;
282
            }
283
        }
284
        return null;
132 ilm 285
    }
286
 
142 ilm 287
    /**
288
     * Get columns user preferences for a specific table
289
     *
290
     * @param configuration - The user SQL configuration
291
     * @param userId - Id of the user who want view the table
292
     *
293
     * @return the XML which contains user preferences
294
     *
295
     * @throws IllegalArgumentException
296
     * @throws IllegalStateException
297
     *
298
     */
299
    // TODO: move in LightUITable, maybe move LightUITable in FrameWork_SQL
300
    private final Document getColumnsSpecUserPerfs(final Configuration configuration, final Number userId) throws IllegalArgumentException, IllegalStateException {
301
        Document columnsPrefs = null;
302
        final DOMBuilder in = new DOMBuilder();
303
        org.w3c.dom.Document w3cDoc = null;
132 ilm 304
 
142 ilm 305
        w3cDoc = configuration.getXMLConf(userId, this.getId());
306
        if (w3cDoc != null) {
307
            columnsPrefs = in.build(w3cDoc);
308
        }
309
        return columnsPrefs;
132 ilm 310
    }
311
 
142 ilm 312
    /**
313
     * Create ColumnsSpec from list of SQLTableModelColumn and apply user preferences
314
     *
315
     * @param configuration - current SQL configuration of user
316
     * @param userId - Id of user
317
     *
318
     * @return New ColumnsSpec with user preferences application
319
     *
320
     * @throws IllegalArgumentException
321
     * @throws IllegalStateException
322
     */
323
    private final ColumnsSpec createColumnsSpecFromModelSource(final Configuration configuration, final Number userId) throws IllegalArgumentException, IllegalStateException {
324
        final List<String> possibleColumnIds = new ArrayList<String>();
325
        final List<String> sortedIds = new ArrayList<String>();
326
        final List<ColumnSpec> columnsSpec = new ArrayList<ColumnSpec>();
132 ilm 327
 
142 ilm 328
        final List<SQLTableModelColumn> columns = this.getModelColumns();
329
        final int columnsCount = columns.size();
330
 
331
        for (int i = 0; i < columnsCount; i++) {
332
            final SQLTableModelColumn sqlColumn = columns.get(i);
333
            // TODO : creer la notion d'ID un peu plus dans le l'esprit sales.invoice.amount
334
            final String columnId = sqlColumn.getIdentifier();
335
 
336
            possibleColumnIds.add(columnId);
337
            Class<?> valueClass = sqlColumn.getValueClass();
338
            if (sqlColumn.getLightUIrenderer() != null) {
339
                valueClass = LightUIElement.class;
132 ilm 340
            }
341
 
142 ilm 342
            columnsSpec.add(new ColumnSpec(columnId, valueClass, sqlColumn.getName(), null, false, null));
132 ilm 343
        }
344
 
142 ilm 345
        // TODO : recuperer l'info sauvegardée sur le serveur par user (à coder)
346
        sortedIds.add(columnsSpec.get(0).getId());
132 ilm 347
 
142 ilm 348
        final ColumnsSpec cSpec = new ColumnsSpec(this.getId(), columnsSpec, possibleColumnIds, sortedIds);
349
        cSpec.setAllowMove(true);
350
        cSpec.setAllowResize(true);
144 ilm 351
        try {
352
            final Document xmlColumnsPref = this.getColumnsSpecUserPerfs(configuration, userId);
353
            if (!cSpec.setUserPrefs(xmlColumnsPref)) {
354
                configuration.removeXMLConf(userId, this.getId());
355
            }
356
        } catch (Exception e) {
357
            System.err.println("LightRowValuesTable.createColumnsSpecFromModelSource() no column pref for conf : " + configuration.getRoot().getName() + " , user id : " + userId);
132 ilm 358
        }
142 ilm 359
 
360
        return cSpec;
132 ilm 361
    }
362
 
142 ilm 363
    // TODO: merge with OpenConcerto List search system
174 ilm 364
    public abstract void doSearch(final Configuration configuration, final UserSearch searchSpec, final int offset);
142 ilm 365
 
174 ilm 366
    public void addSearchParameter(TableSearchParameter tableSearchParameter, TableSearchMatcher tableSearchMatcher) {
367
        this.searchMap.put(tableSearchParameter, tableSearchMatcher);
368
        this.getTableSpec().addSearchParameter(tableSearchParameter);
369
    }
370
 
371
    protected TableSearchMatcher getSearchMatcher(String colId, String searchType) {
372
        for (TableSearchParameter p : this.searchMap.keySet()) {
373
            if (p.getId().equals(colId)) {
374
                for (TableSearchParameterType t : p.getTypes()) {
375
                    if (t.getType().equals(searchType)) {
376
                        return this.searchMap.get(p);
377
                    }
378
                }
379
            }
380
        }
381
        return null;
382
    }
383
 
132 ilm 384
    @Override
142 ilm 385
    public Row getRowById(Number rowId) {
386
        for (int i = 0; i < this.model.getRowCount(); i++) {
387
            if (NumberUtils.areNumericallyEqual(this.model.getRow(i).getID(), rowId)) {
388
                return this.createLightListRowFromListLine(this.model.getRow(i), i);
389
            }
390
        }
391
        return super.getRowById(rowId);
132 ilm 392
    }
393
 
142 ilm 394
    /**
395
     * Create default columns preferences from the SQLTableModelLinesSourceOnline
396
     *
397
     * @return XML document with columns preferences
398
     */
132 ilm 399
    @Override
142 ilm 400
    public Document createDefaultXmlPreferences() {
401
        final Element rootElement = new Element("list");
402
        final List<SQLTableModelColumn> columns = this.getModelColumns();
132 ilm 403
 
142 ilm 404
        final int sqlColumnsCount = columns.size();
405
        for (int i = 0; i < sqlColumnsCount; i++) {
406
            final SQLTableModelColumn sqlColumn = columns.get(i);
407
            final String columnId = sqlColumn.getIdentifier();
408
            final ColumnSpec columnSpec = new ColumnSpec(columnId, sqlColumn.getValueClass(), sqlColumn.getName(), null, false, null);
409
            final Element columnElement = this.createXmlColumn(columnId, columnSpec.getMaxWidth(), columnSpec.getMinWidth(), columnSpec.getWidth());
410
            rootElement.addContent(columnElement);
132 ilm 411
        }
142 ilm 412
        final Document xmlConf = new Document(rootElement);
132 ilm 413
 
142 ilm 414
        return xmlConf;
132 ilm 415
    }
416
 
417
    @Override
142 ilm 418
    public void destroy() {
419
        super.destroy();
132 ilm 420
 
142 ilm 421
        // TODO: clean swing
422
        try {
423
            SwingUtilities.invokeAndWait(new Runnable() {
424
                @Override
425
                public void run() {
174 ilm 426
 
427
                    final List<TableModelListener> listeners = LightRowValuesTable.this.tableModelListeners;
428
                    for (int i = listeners.size() - 1; i > -1; i--) {
429
                        LightRowValuesTable.this.removeTableModelListener(listeners.get(i));
142 ilm 430
                    }
431
                }
432
            });
433
        } catch (final Exception ex) {
434
            throw new IllegalStateException(ex);
132 ilm 435
        }
436
 
142 ilm 437
        this.clearRows();
174 ilm 438
 
132 ilm 439
    }
440
}