OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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