OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 144 | Rev 156 | 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.sql.ui.light;
15
 
16
import org.openconcerto.sql.Configuration;
17
import org.openconcerto.sql.Log;
18
import org.openconcerto.sql.element.SQLElement;
19
import org.openconcerto.sql.model.FieldMapper;
20
import org.openconcerto.sql.model.SQLField;
21
import org.openconcerto.sql.model.SQLRow;
22
import org.openconcerto.sql.model.SQLRowValues;
23
import org.openconcerto.sql.model.SQLTable;
24
import org.openconcerto.sql.view.EditPanel.EditMode;
142 ilm 25
import org.openconcerto.sql.view.list.ListSQLLine;
26
import org.openconcerto.sql.view.list.SQLTableModelLinesSourceOffline;
132 ilm 27
import org.openconcerto.ui.group.Group;
28
import org.openconcerto.ui.group.Item;
29
import org.openconcerto.ui.light.CustomEditorProvider;
30
import org.openconcerto.ui.light.JSONToLightUIConvertor;
31
import org.openconcerto.ui.light.LightUICheckBox;
32
import org.openconcerto.ui.light.LightUIComboBox;
33
import org.openconcerto.ui.light.LightUIDate;
34
import org.openconcerto.ui.light.LightUIElement;
35
import org.openconcerto.ui.light.LightUIFrame;
36
import org.openconcerto.utils.io.JSONConverter;
37
 
142 ilm 38
import java.math.BigDecimal;
132 ilm 39
import java.sql.SQLException;
40
import java.sql.Timestamp;
41
import java.util.Date;
42
import java.util.Map;
142 ilm 43
import java.util.concurrent.Future;
132 ilm 44
 
45
import net.minidev.json.JSONObject;
46
 
47
public class LightEditFrame extends LightUIFrame {
48
    private static final String EDIT_MODE_JSON_KEY = "edit-mode";
49
 
50
    private Group group;
51
    private SQLRowValues sqlRow;
52
 
53
    private EditMode editMode = EditMode.READONLY;
54
 
55
    // Init from json constructor
56
    public LightEditFrame(final JSONObject json) {
57
        super(json);
58
    }
59
 
60
    // Clone constructor
61
    public LightEditFrame(final LightEditFrame frame) {
62
        super(frame);
63
        this.sqlRow = frame.sqlRow;
64
        this.group = frame.group;
65
        this.editMode = frame.editMode;
66
    }
67
 
68
    public LightEditFrame(final Configuration conf, final Group group, final SQLRowValues sqlRow, final LightUIFrame parentFrame, final EditMode editMode) {
69
        super(group.getId() + ".edit.frame");
70
        this.setType(TYPE_FRAME);
71
        this.setParent(parentFrame);
72
 
73
        this.sqlRow = sqlRow;
74
        this.group = group;
75
 
76
        this.setEditMode(editMode);
77
    }
78
 
79
    public void setEditMode(final EditMode editMode) {
80
        this.editMode = editMode;
81
        if (editMode.equals(EditMode.READONLY)) {
82
            this.setReadOnly(true);
83
        } else {
84
            this.setReadOnly(false);
85
        }
86
    }
87
 
88
    /**
89
     * Commit the SQLRowValues attached to this frame
90
     *
142 ilm 91
     * @param configuration - Current configuration
92
     *
132 ilm 93
     * @return The inserted SQLRow
142 ilm 94
     *
95
     * @throws SQLException When an error occur in SQLRowValues.commit()
132 ilm 96
     */
142 ilm 97
    public SQLRow commitSqlRow(final Configuration configuration) throws SQLException {
132 ilm 98
        if (this.editMode.equals(EditMode.READONLY)) {
99
            throw new IllegalArgumentException("Impossible to commit values when the frame is read only");
100
        }
101
        final SQLElement sqlElement = configuration.getDirectory().getElement(this.sqlRow.getTable());
102
        try {
103
            return this.sqlRow.prune(sqlElement.getPrivateGraph()).commit();
104
        } catch (final SQLException ex) {
142 ilm 105
            throw ex;
132 ilm 106
        }
107
    }
108
 
109
    public EditMode getEditMode() {
110
        return this.editMode;
111
    }
112
 
113
    public Group getGroup() {
114
        return this.group;
115
    }
116
 
117
    public SQLRowValues getSqlRow() {
118
        return this.sqlRow;
119
    }
120
 
121
    /**
122
     * Update the SQLRowValues attached to this frame
123
     *
124
     * @param conf
125
     * @param userId
126
     */
142 ilm 127
    public void updateRow(final Configuration configuration, final String sessionSecurityToken, final int userId) {
132 ilm 128
        if (this.editMode.equals(EditMode.READONLY)) {
129
            throw new IllegalArgumentException("Impossible to update values when the frame is read only");
130
        }
142 ilm 131
        this.updateRow(configuration, this.group, sessionSecurityToken, userId);
132 ilm 132
    }
133
 
142 ilm 134
    private void updateRow(final Configuration configuration, final Group group, final String sessionSecurityToken, final int userId) {
132 ilm 135
        final FieldMapper fieldMapper = configuration.getFieldMapper();
136
        if (fieldMapper == null) {
137
            throw new IllegalStateException("null field mapper");
138
        }
139
 
140
        final SQLElement sqlElement = configuration.getDirectory().getElement(this.sqlRow.getTable());
141
 
142 ilm 142
        final Map<String, CustomEditorProvider> customEditors;
132 ilm 143
        if (this.editMode.equals(EditMode.CREATION)) {
142 ilm 144
            customEditors = sqlElement.getCustomEditorProviderForCreation(configuration, sessionSecurityToken);
132 ilm 145
        } else {
142 ilm 146
            customEditors = sqlElement.getCustomEditorProviderForModification(configuration, this.sqlRow, sessionSecurityToken);
132 ilm 147
        }
148
 
142 ilm 149
        this.createRowValues(configuration, sqlElement, fieldMapper, this.group, customEditors);
132 ilm 150
        this.setMetaData(userId);
151
    }
152
 
142 ilm 153
    final protected void createRowValues(final Configuration configuration, final SQLElement sqlElement, final FieldMapper fieldMapper, final Group group,
132 ilm 154
            final Map<String, CustomEditorProvider> customEditors) {
155
        final int itemCount = group.getSize();
156
        for (int i = 0; i < itemCount; i++) {
157
            final Item item = group.getItem(i);
158
            if (item instanceof Group) {
142 ilm 159
                this.createRowValues(configuration, sqlElement, fieldMapper, (Group) item, customEditors);
132 ilm 160
            } else {
161
                final SQLField field = fieldMapper.getSQLFieldForItem(item.getId());
162
                if (field != null) {
144 ilm 163
                    final LightUIElement uiElement = this.findChildByID(item.getId(), LightUIElement.class);
132 ilm 164
 
165
                    if (uiElement == null) {
166
                        throw new IllegalArgumentException("Impossible to find UI Element with id: " + item.getId());
167
                    }
168
 
142 ilm 169
                    if (!uiElement.isNotSaved()) {
170
                        this.putValueFromUserControl(configuration, sqlElement, field, uiElement, customEditors);
132 ilm 171
                    }
172
                } else {
173
                    Log.get().warning("No field attached to " + item.getId());
174
                }
175
            }
176
        }
177
    }
178
 
142 ilm 179
    final protected void putValueFromUserControl(final Configuration configuration, final SQLElement sqlElement, final SQLField sqlField, final LightUIElement uiElement,
180
            final Map<String, CustomEditorProvider> customEditors) {
181
        if (!uiElement.isNotSaved()) {
182
            final Class<?> fieldType = sqlField.getType().getJavaType();
183
            if (customEditors.containsKey(uiElement.getId())) {
184
                final CustomEditorProvider customEditor = customEditors.get(uiElement.getId());
185
                if (customEditor instanceof SavableCustomEditorProvider) {
186
                    ((SavableCustomEditorProvider) customEditor).save(this.sqlRow, sqlField, uiElement);
144 ilm 187
                } else {
188
                    throw new IllegalStateException(customEditor + " must implement SavableCustomEditorProvider for field " + sqlField.getFieldName() + " of tye " + fieldType);
142 ilm 189
                }
190
            } else {
191
                final String fieldName = sqlField.getFieldName();
192
                if (sqlField.isKey()) {
193
                    if (!(uiElement instanceof LightUIComboBox)) {
194
                        throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is foreign key, UI Element must be a LightUIDate");
195
                    }
196
                    final LightUIComboBox combo = (LightUIComboBox) uiElement;
132 ilm 197
 
142 ilm 198
                    if (combo.hasSelectedValue()) {
199
                        this.sqlRow.put(fieldName, combo.getSelectedValue().getId());
200
                    } else {
201
                        this.sqlRow.put(fieldName, null);
202
                    }
203
                } else {
204
                    final String value = uiElement.getValue();
205
                    if (value == null && !sqlField.isNullable()) {
206
                        Log.get().warning("ignoring null value for not nullable field " + fieldName + " from table " + sqlField.getTable().getName());
207
                    } else {
208
                        if (fieldType.equals(String.class)) {
209
                            // FIXME check string size against field size
210
                            this.sqlRow.put(fieldName, value);
211
                        } else if (fieldType.equals(Date.class)) {
212
                            if (!(uiElement instanceof LightUIDate)) {
213
                                throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Date, UI Element must be a LightUIDate");
214
                            }
215
                            this.sqlRow.put(fieldName, ((LightUIDate) uiElement).getValueAsDate());
216
                        } else if (fieldType.equals(Boolean.class)) {
217
                            if (!(uiElement instanceof LightUICheckBox)) {
218
                                throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Boolean, UI Element must be a LightUICheckBox");
219
                            }
220
                            this.sqlRow.put(fieldName, ((LightUICheckBox) uiElement).isChecked());
221
                        } else if (fieldType.equals(Timestamp.class)) {
222
                            if (!(uiElement instanceof LightUIDate)) {
223
                                throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Date, UI Element must be a LightUIDate");
224
                            }
225
                            this.sqlRow.put(fieldName, ((LightUIDate) uiElement).getValueAsDate());
226
                        } else if (fieldType.equals(Integer.class)) {
227
                            if (value != null && !value.trim().isEmpty()) {
228
                                if (!value.matches("^-?\\d+$")) {
229
                                    throw new IllegalArgumentException("Invalid value for field: " + fieldName + " value: " + value);
230
                                }
231
                                this.sqlRow.put(fieldName, Integer.parseInt(value));
232
                            } else {
233
                                this.sqlRow.put(fieldName, null);
234
                            }
235
                        } else if (fieldType.equals(Double.class) || fieldType.equals(Float.class) || fieldType.equals(BigDecimal.class)) {
236
                            if (value != null && !value.trim().isEmpty()) {
237
                                try {
238
                                    this.sqlRow.put(fieldName, new BigDecimal(value));
239
                                } catch (final Exception ex) {
240
                                    throw new IllegalArgumentException("Invalid value for field: " + fieldName + " value: " + value);
241
                                }
132 ilm 242
 
142 ilm 243
                            } else {
244
                                this.sqlRow.put(fieldName, null);
245
                            }
246
                        } else {
247
                            Log.get().warning("unsupported type " + fieldName);
248
                        }
249
                    }
132 ilm 250
                }
251
            }
252
        }
253
    }
254
 
255
    /**
256
     * Save all referent rows store in LightRowValuesTable
257
     *
258
     * @param group Element edit group
259
     * @param frame Element edit frame
260
     * @param row Element saved row
261
     * @param customEditors List of custom editors used in element edit frame
262
     */
142 ilm 263
    final public void saveReferentRows(final Configuration configuration, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, final String sessionSecurityToken) {
264
        this.saveReferentRows(configuration, this.group, parentSqlRow, customEditors, sessionSecurityToken);
132 ilm 265
    }
266
 
142 ilm 267
    final private void saveReferentRows(final Configuration configuration, final Group group, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors,
268
            final String sessionSecurityToken) {
132 ilm 269
        for (int i = 0; i < group.getSize(); i++) {
270
            final Item item = group.getItem(i);
271
            if (item instanceof Group) {
142 ilm 272
                this.saveReferentRows(configuration, (Group) item, parentSqlRow, customEditors, sessionSecurityToken);
132 ilm 273
            } else if (customEditors.containsKey(item.getId())) {
144 ilm 274
                final LightUIElement element = this.findChildByID(item.getId(), LightUIElement.class);
142 ilm 275
                if (element instanceof LightForeignRowValuesTableOffline) {
276
                    final LightForeignRowValuesTableOffline foreignTable = (LightForeignRowValuesTableOffline) element;
277
                    for (int j = 0; j < foreignTable.getRowsCount(); j++) {
278
                        final ListSQLLine listLine = foreignTable.getModel().getRow(j);
279
                        final SQLRowValues rowVals = listLine.getRow().createEmptyUpdateRow();
280
                        rowVals.put(foreignTable.getForeignField().getName(), parentSqlRow.getID());
281
                        ((SQLTableModelLinesSourceOffline) foreignTable.getModel().getLinesSource()).updateRow(listLine.getID(), rowVals);
132 ilm 282
                    }
142 ilm 283
                    final Future<?> fCommit = foreignTable.commitRows();
284
 
285
                    try {
286
                        fCommit.get();
287
                    } catch (final Exception ex) {
288
                        throw new IllegalArgumentException(ex);
289
                    }
132 ilm 290
                }
291
            }
292
        }
293
    }
294
 
151 ilm 295
    // FIXME use SQLRowValues method
296
    protected final void setMetaData(final int userId) {
132 ilm 297
        final SQLTable sqlTable = this.sqlRow.getTable();
151 ilm 298
        final Date now = new Date();
299
        // FIXME only set those fields at insertion time
132 ilm 300
        if (this.sqlRow.getObject(sqlTable.getCreationUserField().getName()) == null || this.sqlRow.getObject(sqlTable.getCreationDateField().getName()) == null) {
151 ilm 301
            setFieldValue(this.sqlRow, sqlTable.getCreationUserField(), false, userId);
302
            setFieldValue(this.sqlRow, sqlTable.getCreationDateField(), false, now);
132 ilm 303
        }
151 ilm 304
        setFieldValue(this.sqlRow, sqlTable.getModifUserField(), false, userId);
305
        setFieldValue(this.sqlRow, sqlTable.getModifDateField(), false, now);
132 ilm 306
    }
307
 
151 ilm 308
    static private boolean setFieldValue(final SQLRowValues vals, final SQLField f, final boolean remove, final Object val) {
309
        if (f == null)
310
            return false;
311
        if (remove)
312
            vals.remove(f.getName());
313
        else
314
            vals.put(f.getName(), val);
315
        return true;
316
    }
317
 
132 ilm 318
    @Override
319
    public String getClassName() {
320
        return this.getClass().getName();
321
    }
322
 
323
    @Override
324
    public JSONToLightUIConvertor getConvertor() {
325
        return new JSONToLightUIConvertor() {
326
 
327
            @Override
328
            public LightUIElement convert(JSONObject json) {
329
                return new LightEditFrame(json);
330
            }
331
        };
332
    }
333
 
334
    @Override
335
    public LightUIElement clone() {
336
        return new LightEditFrame(this);
337
    }
338
 
339
    // TODO: implement JSONAble on SQLRowValues and Group
340
    @Override
341
    public JSONObject toJSON() {
342
        final JSONObject json = super.toJSON();
343
        if (!this.editMode.equals(EditMode.READONLY)) {
344
            if (this.editMode.equals(EditMode.CREATION)) {
345
                json.put(EDIT_MODE_JSON_KEY, 1);
346
            } else if (this.editMode.equals(EditMode.MODIFICATION)) {
347
                json.put(EDIT_MODE_JSON_KEY, 2);
348
            }
349
        }
350
        return json;
351
    }
352
 
353
    @Override
354
    public void fromJSON(final JSONObject json) {
355
        super.fromJSON(json);
356
        final int jsonEditMode = JSONConverter.getParameterFromJSON(json, EDIT_MODE_JSON_KEY, Integer.class, 3);
357
        if (jsonEditMode == 1) {
358
            this.editMode = EditMode.CREATION;
359
        } else if (jsonEditMode == 2) {
360
            this.editMode = EditMode.MODIFICATION;
361
        } else if (jsonEditMode == 3) {
362
            this.editMode = EditMode.READONLY;
363
        }
364
    }
365
}