OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 149 | Go to most recent revision | 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.erp.core.common.element;
15
 
16
import org.openconcerto.sql.Configuration;
17
import org.openconcerto.sql.PropsConfiguration;
18
import org.openconcerto.sql.element.SQLElement;
19
import org.openconcerto.sql.model.FieldPath;
20
import org.openconcerto.sql.model.SQLField;
142 ilm 21
import org.openconcerto.sql.model.SQLRowAccessor;
132 ilm 22
import org.openconcerto.sql.model.SQLRowValues;
23
import org.openconcerto.sql.model.SQLTable;
24
import org.openconcerto.sql.model.SQLTable.VirtualFields;
25
import org.openconcerto.sql.model.Where;
142 ilm 26
import org.openconcerto.sql.request.ComboSQLRequest;
132 ilm 27
import org.openconcerto.sql.request.ListSQLRequest;
28
import org.openconcerto.sql.request.SQLFieldTranslator;
29
import org.openconcerto.sql.ui.light.GroupToLightUIConvertor;
30
import org.openconcerto.sql.view.EditPanel.EditMode;
144 ilm 31
import org.openconcerto.sql.view.list.RowAction;
132 ilm 32
import org.openconcerto.sql.view.list.SQLTableModelColumn;
142 ilm 33
import org.openconcerto.sql.view.list.SQLTableModelSource;
132 ilm 34
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
144 ilm 35
import org.openconcerto.sql.view.list.TableAction;
132 ilm 36
import org.openconcerto.ui.AutoHideListener;
37
import org.openconcerto.ui.light.InformationLine;
38
import org.openconcerto.ui.light.LightUIElement;
39
import org.openconcerto.ui.light.LightUILine;
40
import org.openconcerto.ui.light.LightUIPanel;
41
import org.openconcerto.ui.light.RowSelectionSpec;
42
import org.openconcerto.ui.light.SimpleTextLine;
43
import org.openconcerto.ui.table.TableCellRendererUtils;
44
import org.openconcerto.utils.GestionDevise;
45
import org.openconcerto.utils.convertor.ValueConvertor;
46
 
47
import java.awt.Color;
48
import java.awt.Component;
144 ilm 49
import java.awt.event.ActionEvent;
132 ilm 50
import java.lang.reflect.Modifier;
51
import java.math.BigDecimal;
52
import java.math.BigInteger;
53
import java.util.ArrayList;
54
import java.util.List;
55
 
144 ilm 56
import javax.swing.AbstractAction;
132 ilm 57
import javax.swing.JLabel;
58
import javax.swing.JPanel;
59
import javax.swing.JTable;
60
import javax.swing.SwingConstants;
61
import javax.swing.table.DefaultTableCellRenderer;
62
import javax.swing.table.TableCellRenderer;
63
 
64
import org.jdom2.Document;
65
import org.jdom2.input.DOMBuilder;
66
 
67
/**
68
 * SQLElement de la base société
69
 *
70
 * @author Administrateur
71
 *
72
 */
73
public abstract class SocieteSQLConfElement extends SQLElement {
144 ilm 74
    public static final String ACTION_ID_ADD = "add";
75
    public static final String ACTION_ID_MODIFY = "modify";
76
    public static final String ACTION_ID_REMOVE = "remove";
132 ilm 77
 
78
    public SocieteSQLConfElement(SQLTable table, String singular, String plural) {
79
        super(singular, plural, table);
80
    }
81
 
82
    public SocieteSQLConfElement(SQLTable table) {
83
        this(table, null);
84
    }
85
 
86
    public SocieteSQLConfElement(SQLTable table, String code) {
87
        super(table, null, code);
88
    }
89
 
90
    public static final TableCellRenderer CURRENCY_RENDERER = new DefaultTableCellRenderer() {
91
        @Override
92
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
93
            final Component res = super.getTableCellRendererComponent(table, GestionDevise.currencyToString((BigDecimal) value), isSelected, hasFocus, row, column);
94
            // this renderer can be decorated by e.g. ListeFactureRenderer which does a
95
            // setBackground(), thus always reset the colors
96
            // MAYBE always use ProxyComp as in AlternateTableCellRenderer to leave the decorated
97
            // renderer as found
98
            TableCellRendererUtils.setColors(res, table, isSelected);
99
            ((JLabel) res).setHorizontalAlignment(SwingConstants.RIGHT);
100
            return res;
101
        }
102
    };
103
 
104
    static public final JPanel createAdditionalPanel() {
105
        return AutoHideListener.listen(new JPanel());
106
    }
107
 
108
    @Override
109
    protected String createCode() {
156 ilm 110
        final String suffix = this.createCodeSuffix();
111
        if (suffix.indexOf(' ') >= 0)
112
            throw new IllegalStateException("Suffix contains space : '" + suffix + "'");
113
        if (suffix.length() < 2)
114
            throw new IllegalStateException("Suffix too short : '" + suffix + "'");
115
        return createCodeOfPackage() + suffix;
132 ilm 116
    }
117
 
156 ilm 118
    protected String createCodeSuffix() {
119
        return this.createCodeSuffixFromTable();
120
    }
121
 
122
    protected final String createCodeSuffixFromTable() {
123
        return '.' + this.getTable().getName();
124
    }
125
 
132 ilm 126
    /**
127
     * Return a code that doesn't change when subclassing to allow to easily change a SQLElement
128
     * while keeping the same code. To achieve that, the code isn't
156 ilm 129
     * {@link #createCodeOfPackage(Class) computed} with <code>this.getClass()</code>. We iterate up
130
     * through our superclass chain, and as soon as we find an abstract class, we stop and use the
131
     * previous class (i.e. non abstract). E.g. any direct subclass of {@link ComptaSQLConfElement}
132
     * will still use <code>this.getClass()</code>, but so is one of its subclass.
132 ilm 133
     *
134
     * @return a code computed from the superclass just under the first abstract superclass.
156 ilm 135
     * @see #createCodeOfPackage(Class)
132 ilm 136
     */
156 ilm 137
    protected final String createCodeOfPackage() {
138
        return createCodeOfPackage(getLastNonAbstractClass());
132 ilm 139
    }
140
 
149 ilm 141
    private final Class<? extends SocieteSQLConfElement> getLastNonAbstractClass() {
142
        return getLastNonAbstractClass(this.getClass(), SocieteSQLConfElement.class);
143
    }
144
 
145
    static protected final <T extends SQLElement> Class<? extends T> getLastNonAbstractClass(final Class<? extends T> clazz, final Class<T> superClass) {
132 ilm 146
        Class<?> prev = null;
149 ilm 147
        Class<?> cl = clazz;
132 ilm 148
        // test loop
149 ilm 149
        assert superClass.isAssignableFrom(cl);
150
        if (Modifier.isAbstract(cl.getModifiers()))
151
            throw new IllegalArgumentException("Class is abstract : " + cl);
152
        if (!Modifier.isAbstract(superClass.getModifiers()))
153
            throw new IllegalArgumentException("Superclass isn't abstract : " + superClass);
132 ilm 154
        while (!Modifier.isAbstract(cl.getModifiers())) {
155
            prev = cl;
156
            cl = cl.getSuperclass();
157
        }
149 ilm 158
        return prev.asSubclass(superClass);
132 ilm 159
    }
160
 
156 ilm 161
    static private final String ERP_CORE = ".erp.core.";
162
    static private final String ERP_ELEMENT = ".erp.element.";
163
 
164
    static protected String createCodeOfPackage(final Class<? extends SQLElement> cl) {
165
        String canonicalName = cl.getPackage().getName();
166
        if (canonicalName.contains(ERP_CORE) && canonicalName.contains(".element")) {
167
            int i = canonicalName.indexOf(ERP_CORE) + ERP_CORE.length();
132 ilm 168
            int j = canonicalName.indexOf(".element");
169
            canonicalName = canonicalName.substring(i, j);
156 ilm 170
        } else if (canonicalName.contains(ERP_ELEMENT)) {
171
            canonicalName = canonicalName.substring(canonicalName.indexOf(ERP_ELEMENT) + ERP_ELEMENT.length());
132 ilm 172
        }
173
        return canonicalName;
174
    }
175
 
176
    @Override
142 ilm 177
    protected void _initTableSource(SQLTableModelSource res) {
132 ilm 178
        super._initTableSource(res);
179
        for (final SQLTableModelColumn col : res.getColumns()) {
180
            // TODO getDeviseFields()
181
            if (col.getValueClass() == Long.class || col.getValueClass() == BigInteger.class) {
182
                col.setConverter(new ValueConvertor<Number, BigDecimal>() {
183
                    @Override
184
                    public BigDecimal convert(Number o) {
185
                        if (o == null) {
186
                            System.err.println("ComptaSQLConfElement._initTableSource: Warning null Number conversion (" + this + ")");
187
                            return BigDecimal.ZERO;
188
                        }
189
                        return new BigDecimal(o.longValue()).movePointLeft(2);
190
                    }
191
 
192
                    @Override
193
                    public Number unconvert(BigDecimal o) {
194
 
195
                        if (o == null) {
196
                            System.err.println("ComptaSQLConfElement._initTableSource: Warning null BigDecimal conversion (" + this + ")");
197
                            return 0;
198
                        }
199
                        return o.movePointRight(2);
200
                    }
201
                }, BigDecimal.class);
202
                col.setRenderer(CURRENCY_RENDERER);
203
            }
204
        }
205
    }
206
 
207
    /**
208
     * Get columns user preferences for a specific table
209
     *
210
     * @param userId - Id of the user who want view the table
211
     * @param tableId - Id of table to show
212
     * @param sqlColumns - List of columns to be displayed
213
     * @return the XML which contains user preferences
214
     */
215
    protected Document getColumnsUserPerfs(final Configuration configuration, final int userId, final String tableId, final List<SQLTableModelColumn> sqlColumns) {
216
        Document columnsPrefs = null;
217
        try {
218
            final DOMBuilder in = new DOMBuilder();
219
            final org.w3c.dom.Document w3cDoc = configuration.getXMLConf(userId, tableId);
220
            if (w3cDoc != null) {
221
                columnsPrefs = in.build(w3cDoc);
222
            }
223
        } catch (Exception ex) {
224
            throw new IllegalArgumentException("Failed to get ColumnPrefs for table " + tableId + " and for user " + userId + "\n" + ex.getMessage());
225
        }
226
 
227
        return columnsPrefs;
228
    }
229
 
230
    /**
231
     * Create buttons from SQLElement secondary row actions
232
     */
233
    public LightUILine createSecondaryRowActionLine(final RowSelectionSpec selection) {
234
        return null;
235
    }
236
 
237
    /**
238
     * Create information ui panel for selected lines. By default, all fields in SQLRowValues are
239
     * displayed
240
     *
142 ilm 241
     * @param sessionToken - String use to find session on server
242
     * @param selection - List of SQLRowAccessor attach to selected lines
243
     *
244
     * @return null if selection is empty or a LightUIPanel
132 ilm 245
     */
142 ilm 246
    public final LightUIPanel createDataPanel(final String sessionToken, final List<SQLRowAccessor> selection) {
247
        if (selection == null || selection.isEmpty()) {
132 ilm 248
            return null;
249
        }
142 ilm 250
        final LightUIPanel dataPanel = new LightUIPanel(this.getCode() + ".data.panel");
251
        dataPanel.setVerticallyScrollable(true);
252
        dataPanel.setWeightX(1);
253
        dataPanel.setMarginLeft(4);
254
        this.fillDataPanel(sessionToken, selection, dataPanel);
132 ilm 255
 
142 ilm 256
        return dataPanel;
257
    }
258
 
259
    protected void fillDataPanel(final String sessionToken, final List<SQLRowAccessor> selection, final LightUIPanel dataPanel) {
260
        final SQLFieldTranslator translator = this.getDirectory().getTranslator();
261
 
262
        for (final SQLRowAccessor listRow : selection) {
263
            final int rowId = listRow.getID();
132 ilm 264
            final LightUILine mainLine = new LightUILine();
142 ilm 265
            final LightUIPanel mainLinePanel = new LightUIPanel(dataPanel.getId() + ".main.line." + rowId);
132 ilm 266
            mainLinePanel.setWeightX(1);
267
            mainLinePanel.addChild(new SimpleTextLine("Information sur l'élément n°" + rowId, true, LightUIElement.HALIGN_CENTER));
268
            final LightUILine lineData = new LightUILine();
142 ilm 269
            final LightUIPanel panel = new LightUIPanel(this.getCode() + ".data.panel." + rowId);
270
            panel.setWeightX(1);
144 ilm 271
 
142 ilm 272
            final List<String> dataPanelFields = this.getDataPanelFields();
273
            for (final String fieldName : dataPanelFields) {
274
                this.addFieldToPanel(fieldName, panel, listRow, translator);
132 ilm 275
            }
142 ilm 276
            lineData.addChild(panel);
132 ilm 277
            mainLinePanel.addChild(lineData);
278
            mainLine.addChild(mainLinePanel);
142 ilm 279
 
280
            dataPanel.addChild(mainLine);
132 ilm 281
        }
282
    }
144 ilm 283
 
284
    protected List<String> getDataPanelFields() {
142 ilm 285
        return this.getListFields();
286
    }
132 ilm 287
 
142 ilm 288
    public void addFieldToPanel(final String fieldName, final LightUIPanel dataPanel, final SQLRowAccessor sqlRow, final SQLFieldTranslator translator) {
289
        addFieldToPanel(fieldName, dataPanel, sqlRow, translator, false, "");
132 ilm 290
    }
291
 
292
    static private final VirtualFields FIELDS_TO_IGNORE = VirtualFields.PRIMARY_KEY.union(VirtualFields.ARCHIVE).union(VirtualFields.ORDER);
293
 
294
    /**
295
     * Add the field name translation and it's value to the information panel
296
     *
297
     * @param fieldName - Field to be translate
298
     * @param dataPanel - Information panel
142 ilm 299
     * @param sqlRow - Row which contains data
132 ilm 300
     * @param translator - Field translator
301
     */
142 ilm 302
    public void addFieldToPanel(final String fieldName, final LightUIPanel dataPanel, final SQLRowAccessor sqlRow, final SQLFieldTranslator translator, boolean addEmpty, String defaultValue) {
303
        final SQLTable sqlTable = sqlRow.getTable();
304
        final SQLField field = sqlTable.getField(fieldName);
305
 
306
        if (!sqlTable.getFields(FIELDS_TO_IGNORE).contains(field)) {
132 ilm 307
            String key = translator.getLabelFor(field);
308
            boolean error = false;
309
            if (key == null) {
310
                error = true;
311
                key = field.getFieldName();
312
            }
313
 
314
            String value = "";
315
            if (field.isKey()) {
316
                final List<FieldPath> fieldsPath = getListExpander().expand(field);
317
                for (FieldPath fieldPath : fieldsPath) {
142 ilm 318
                    final SQLRowValues foreignRow = sqlRow.asRowValues().followPath(fieldPath.getPath());
132 ilm 319
                    if (foreignRow != null) {
320
                        value += foreignRow.getString(fieldPath.getField().getName()) + " ";
321
                    }
322
                }
323
            } else {
142 ilm 324
                value = sqlRow.getString(fieldName);
132 ilm 325
            }
326
            boolean isDefault = false;
327
            if (value == null || value.isEmpty()) {
328
                isDefault = true;
329
                value = defaultValue;
330
            }
331
            if (!value.isEmpty() || addEmpty) {
332
                final InformationLine line = new InformationLine(key, value);
333
                if (error) {
334
                    line.setLabelColor(Color.RED);
335
                }
336
                line.setItalicOnValue(isDefault);
337
                dataPanel.addChild(line);
338
            }
339
        }
340
    }
341
 
142 ilm 342
    public GroupToLightUIConvertor getGroupToLightUIConvertor(final PropsConfiguration configuration, final EditMode editMode, final SQLRowValues sqlRow, final String sessionSecurityToken) {
132 ilm 343
        final GroupToLightUIConvertor convertor = new GroupToLightUIConvertor(configuration);
344
        if (editMode.equals(EditMode.CREATION)) {
142 ilm 345
            convertor.putAllCustomEditorProvider(this.getCustomEditorProviderForCreation(configuration, sessionSecurityToken));
132 ilm 346
        } else {
142 ilm 347
            convertor.putAllCustomEditorProvider(this.getCustomEditorProviderForModification(configuration, sqlRow, sessionSecurityToken));
132 ilm 348
        }
349
        return convertor;
350
    }
351
 
352
    public List<SQLRowValues> getRowValues(final String fieldName, final long id) {
353
        final SQLTableModelSourceOnline tableSource = this.getTableSource(true);
354
 
355
        final ListSQLRequest req = tableSource.getReq();
356
        req.setWhere(new Where(this.getTable().getField(fieldName), "=", id));
357
        return req.getValues();
358
    }
359
 
142 ilm 360
    @Override
361
    protected void _initComboRequest(ComboSQLRequest req) {
362
        super._initComboRequest(req);
363
        req.setSearchable(true);
132 ilm 364
    }
144 ilm 365
 
366
    /**
367
     * Primary actions on the element (add/modify/remove)
368
     */
369
    public List<TableAction> getPrimaryRowActions() {
149 ilm 370
        final List<TableAction> actions = new ArrayList<>(3);
144 ilm 371
        actions.add(new TableAction(getAddAction()));
372
        actions.add(new TableAction(getModifyAction()));
373
        actions.add(new TableAction(getRemoveAction()));
374
        return actions;
375
    }
376
 
377
    /**
378
     * Secondary actions on the element (send by email, ..)
379
     */
380
    public List<TableAction> getSecondaryRowActions() {
149 ilm 381
        return new ArrayList<>(0);
144 ilm 382
    }
383
 
384
    public RowAction getAddAction() {
385
        return new RowAction(new AbstractAction() {
386
            public void actionPerformed(ActionEvent e) {
387
                // nothing here because use on an ActionButtonWithSelection
388
            }
389
        }, true, ACTION_ID_ADD) {
390
 
391
            @Override
392
            public boolean enabledFor(final List<SQLRowValues> selection) {
393
                return true;
394
            };
395
 
396
        };
397
    }
398
 
399
    public RowAction getModifyAction() {
400
        final RowAction rowAction = new RowAction(new AbstractAction() {
401
            public void actionPerformed(ActionEvent e) {// nothing here because use on an
402
                                                        // ActionButtonWithSelection
403
            }
404
 
405
        }, true, ACTION_ID_MODIFY) {
406
 
407
            @Override
408
            public boolean enabledFor(final List<SQLRowValues> selection) {
409
                return (selection != null && selection.size() == 1);
410
            };
411
 
412
        };
413
 
414
        return rowAction;
415
    }
416
 
417
    public RowAction getRemoveAction() {
418
        return new RowAction(new AbstractAction() {
419
            public void actionPerformed(ActionEvent e) {// nothing here because use on an
420
                                                        // ActionButtonWithSelection
421
            }
422
        }, true, ACTION_ID_REMOVE) {
423
 
424
            @Override
425
            public boolean enabledFor(final List<SQLRowValues> selection) {
426
                return (selection != null && !selection.isEmpty());
427
            };
428
        };
429
    }
132 ilm 430
}