Dépôt officiel du code source de l'ERP OpenConcerto
Rev 156 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU General Public License Version 3
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*/
package org.openconcerto.sql.ui.light;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.Log;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.FieldMapper;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.view.EditPanel.EditMode;
import org.openconcerto.sql.view.list.ListSQLLine;
import org.openconcerto.sql.view.list.SQLTableModelLinesSourceOffline;
import org.openconcerto.ui.group.Group;
import org.openconcerto.ui.group.Item;
import org.openconcerto.ui.light.CustomEditorProvider;
import org.openconcerto.ui.light.LightUICheckBox;
import org.openconcerto.ui.light.LightUIComboBox;
import org.openconcerto.ui.light.LightUIDate;
import org.openconcerto.ui.light.LightUIElement;
import org.openconcerto.ui.light.LightUIFrame;
import org.openconcerto.utils.io.JSONConverter;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import net.minidev.json.JSONObject;
public class LightEditFrame extends LightUIFrame {
private static final String EDIT_MODE_JSON_KEY = "edit-mode";
private Group group;
private SQLRowValues sqlRow;
private EditMode editMode = EditMode.READONLY;
public LightEditFrame() {
// Serialization
}
// Init from json constructor
public LightEditFrame(final JSONObject json) {
super(json);
}
// Clone constructor
public LightEditFrame(final LightEditFrame frame) {
super(frame);
this.sqlRow = frame.sqlRow;
this.group = frame.group;
this.editMode = frame.editMode;
}
public LightEditFrame(final Configuration conf, final Group group, final SQLRowValues sqlRow, final LightUIFrame parentFrame, final EditMode editMode) {
super(group.getId() + ".edit.frame");
this.setType(TYPE_FRAME);
this.setParent(parentFrame);
this.sqlRow = sqlRow;
this.group = group;
this.setEditMode(editMode);
}
public void setEditMode(final EditMode editMode) {
this.editMode = editMode;
if (editMode.equals(EditMode.READONLY)) {
this.setReadOnly(true);
} else {
this.setReadOnly(false);
}
}
/**
* Commit the SQLRowValues attached to this frame
*
* @param configuration - Current configuration
*
* @return The inserted SQLRow
*
* @throws SQLException When an error occur in SQLRowValues.commit()
*/
public SQLRow commitSqlRow(final Configuration configuration) throws SQLException {
if (this.editMode.equals(EditMode.READONLY)) {
throw new IllegalArgumentException("Impossible to commit values when the frame is read only");
}
final SQLElement sqlElement = configuration.getDirectory().getElement(this.sqlRow.getTable());
try {
return this.sqlRow.prune(sqlElement.getPrivateGraph()).commit();
} catch (final SQLException ex) {
throw ex;
}
}
public EditMode getEditMode() {
return this.editMode;
}
public Group getGroup() {
return this.group;
}
public SQLRowValues getSqlRow() {
return this.sqlRow;
}
/**
* Update the SQLRowValues attached to this frame
*
* @param conf
* @param userId
*/
public void updateRow(final Configuration configuration, final String sessionSecurityToken, final int userId) {
if (this.editMode.equals(EditMode.READONLY)) {
throw new IllegalArgumentException("Impossible to update values when the frame is read only");
}
this.updateRow(configuration, this.group, sessionSecurityToken, userId);
}
private void updateRow(final Configuration configuration, final Group group, final String sessionSecurityToken, final int userId) {
final FieldMapper fieldMapper = configuration.getFieldMapper();
if (fieldMapper == null) {
throw new IllegalStateException("null field mapper");
}
final SQLElement sqlElement = configuration.getDirectory().getElement(this.sqlRow.getTable());
final List<CustomRowEditor> customRowEditors = sqlElement.getCustomRowEditors(configuration, sessionSecurityToken);
final Map<String, CustomRowEditor> customEditors = new HashMap<>(customRowEditors.size());
for (CustomRowEditor e : customRowEditors) {
customEditors.put(e.getItemId(), e);
}
this.createRowValues(configuration, sqlElement, fieldMapper, this.group, customEditors);
this.setMetaData(userId);
}
protected final void createRowValues(final Configuration configuration, final SQLElement sqlElement, final FieldMapper fieldMapper, final Group group,
final Map<String, CustomRowEditor> customEditors) {
final int itemCount = group.getSize();
for (int i = 0; i < itemCount; i++) {
final Item item = group.getItem(i);
if (item instanceof Group) {
this.createRowValues(configuration, sqlElement, fieldMapper, (Group) item, customEditors);
} else {
final SQLField field = fieldMapper.getSQLFieldForItem(item.getId());
if (field != null) {
final LightUIElement uiElement = this.findChildByID(item.getId(), LightUIElement.class);
if (uiElement == null) {
throw new IllegalArgumentException("Impossible to find UI Element with id: " + item.getId());
}
if (!uiElement.isNotSaved()) {
this.putValueFromUserControl(configuration, sqlElement, field, uiElement, customEditors);
}
} else {
final LightUIElement uiElement = this.findChildByID(item.getId(), LightUIElement.class);
if (uiElement == null) {
throw new IllegalArgumentException("Impossible to find UI Element with id: " + item.getId());
}
if (customEditors.containsKey(uiElement.getId())) {
final CustomRowEditor customEditor = customEditors.get(uiElement.getId());
customEditor.store(uiElement, this.sqlRow);
} else {
Log.get().warning("No field attached to " + item.getId());
}
}
}
}
}
protected final void putValueFromUserControl(final Configuration configuration, final SQLElement sqlElement, final SQLField sqlField, final LightUIElement uiElement,
final Map<String, CustomRowEditor> customEditors) {
if (!uiElement.isNotSaved()) {
final Class<?> fieldType = sqlField.getType().getJavaType();
if (customEditors.containsKey(uiElement.getId())) {
final CustomRowEditor customEditor = customEditors.get(uiElement.getId());
customEditor.store(uiElement, this.sqlRow);
} else {
final String fieldName = sqlField.getFieldName();
if (sqlField.isKey()) {
if (!(uiElement instanceof LightUIComboBox)) {
throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is foreign key, UI Element must be a LightUIDate");
}
final LightUIComboBox combo = (LightUIComboBox) uiElement;
if (combo.hasSelectedValue()) {
this.sqlRow.put(fieldName, combo.getSelectedValue().getId());
} else {
this.sqlRow.put(fieldName, null);
}
} else {
final String value = uiElement.getValue();
if (value == null && !sqlField.isNullable()) {
Log.get().warning("ignoring null value for not nullable field " + fieldName + " from table " + sqlField.getTable().getName());
} else {
if (fieldType.equals(String.class)) {
// FIXME check string size against field size
this.sqlRow.put(fieldName, value);
} else if (fieldType.equals(Date.class)) {
if (!(uiElement instanceof LightUIDate)) {
throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Date, UI Element must be a LightUIDate");
}
this.sqlRow.put(fieldName, ((LightUIDate) uiElement).getValueAsDate());
} else if (fieldType.equals(Boolean.class)) {
if (!(uiElement instanceof LightUICheckBox)) {
throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Boolean, UI Element must be a LightUICheckBox");
}
this.sqlRow.put(fieldName, ((LightUICheckBox) uiElement).isChecked());
} else if (fieldType.equals(Timestamp.class)) {
if (!(uiElement instanceof LightUIDate)) {
throw new IllegalArgumentException("Invalid UI Element for field: " + fieldName + ". When field is Date, UI Element must be a LightUIDate");
}
this.sqlRow.put(fieldName, ((LightUIDate) uiElement).getValueAsDate());
} else if (fieldType.equals(Integer.class)) {
if (value != null && !value.trim().isEmpty()) {
if (!value.matches("^-?\\d+$")) {
throw new IllegalArgumentException("Invalid value for field: " + fieldName + " value: " + value);
}
this.sqlRow.put(fieldName, Integer.parseInt(value));
} else {
this.sqlRow.put(fieldName, null);
}
} else if (fieldType.equals(Double.class) || fieldType.equals(Float.class) || fieldType.equals(BigDecimal.class)) {
if (value != null && !value.trim().isEmpty()) {
try {
this.sqlRow.put(fieldName, new BigDecimal(value));
} catch (final Exception ex) {
throw new IllegalArgumentException("Invalid value for field: " + fieldName + " value: " + value);
}
} else {
this.sqlRow.put(fieldName, null);
}
} else {
Log.get().warning("unsupported type " + fieldName);
}
}
}
}
}
}
/**
* Save all referent rows store in LightRowValuesTable
*
* @param group Element edit group
* @param frame Element edit frame
* @param row Element saved row
* @param customEditors List of custom editors used in element edit frame
*/
@Deprecated
public final void saveReferentRows(final Configuration configuration, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors, final String sessionSecurityToken) {
this.saveReferentRows(configuration, this.group, parentSqlRow, customEditors, sessionSecurityToken);
}
@Deprecated
private final void saveReferentRows(final Configuration configuration, final Group group, final SQLRow parentSqlRow, final Map<String, CustomEditorProvider> customEditors,
final String sessionSecurityToken) {
for (int i = 0; i < group.getSize(); i++) {
final Item item = group.getItem(i);
if (item instanceof Group) {
this.saveReferentRows(configuration, (Group) item, parentSqlRow, customEditors, sessionSecurityToken);
} else if (customEditors.containsKey(item.getId())) {
final LightUIElement element = this.findChildByID(item.getId(), LightUIElement.class);
if (element instanceof LightForeignRowValuesTableOffline) {
final LightForeignRowValuesTableOffline foreignTable = (LightForeignRowValuesTableOffline) element;
for (int j = 0; j < foreignTable.getRowsCount(); j++) {
final ListSQLLine listLine = foreignTable.getModel().getRow(j);
final SQLRowValues rowVals = listLine.getRow().createEmptyUpdateRow();
rowVals.put(foreignTable.getForeignField().getName(), parentSqlRow.getID());
((SQLTableModelLinesSourceOffline) foreignTable.getModel().getLinesSource()).updateRow(listLine.getID(), rowVals);
}
final Future<?> fCommit = foreignTable.commitRows();
try {
fCommit.get();
} catch (final Exception ex) {
throw new IllegalArgumentException(ex);
}
}
}
}
}
// FIXME use SQLRowValues method
protected final void setMetaData(final int userId) {
final SQLTable sqlTable = this.sqlRow.getTable();
final Date now = new Date();
// FIXME only set those fields at insertion time
if (sqlTable.getCreationUserField() != null) {
if (this.sqlRow.getObject(sqlTable.getCreationUserField().getName()) == null || this.sqlRow.getObject(sqlTable.getCreationDateField().getName()) == null) {
setFieldValue(this.sqlRow, sqlTable.getCreationUserField(), false, userId);
setFieldValue(this.sqlRow, sqlTable.getCreationDateField(), false, now);
}
}
if (sqlTable.getModifUserField() != null) {
setFieldValue(this.sqlRow, sqlTable.getModifUserField(), false, userId);
setFieldValue(this.sqlRow, sqlTable.getModifDateField(), false, now);
}
}
static private boolean setFieldValue(final SQLRowValues vals, final SQLField f, final boolean remove, final Object val) {
if (f == null)
return false;
if (remove)
vals.remove(f.getName());
else
vals.put(f.getName(), val);
return true;
}
@Override
public String getClassName() {
return this.getClass().getName();
}
@Override
public LightUIElement clone() {
return new LightEditFrame(this);
}
// TODO: implement JSONAble on SQLRowValues and Group
@Override
public JSONObject toJSON() {
final JSONObject json = super.toJSON();
if (!this.editMode.equals(EditMode.READONLY)) {
if (this.editMode.equals(EditMode.CREATION)) {
json.put(EDIT_MODE_JSON_KEY, 1);
} else if (this.editMode.equals(EditMode.MODIFICATION)) {
json.put(EDIT_MODE_JSON_KEY, 2);
}
}
return json;
}
@Override
public void fromJSON(final JSONObject json) {
super.fromJSON(json);
final int jsonEditMode = JSONConverter.getParameterFromJSON(json, EDIT_MODE_JSON_KEY, Integer.class, 3);
if (jsonEditMode == 1) {
this.editMode = EditMode.CREATION;
} else if (jsonEditMode == 2) {
this.editMode = EditMode.MODIFICATION;
} else if (jsonEditMode == 3) {
this.editMode = EditMode.READONLY;
}
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
if (this.editMode.equals(EditMode.CREATION)) {
out.writeByte(0);
} else if (this.editMode.equals(EditMode.MODIFICATION)) {
out.writeByte(1);
} else if (this.editMode.equals(EditMode.READONLY)) {
out.writeByte(2);
} else {
throw new IllegalStateException("unknown mode " + this.editMode);
}
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
int mode = in.readByte();
if (mode == 0) {
this.editMode = EditMode.CREATION;
} else if (mode == 1) {
this.editMode = EditMode.MODIFICATION;
} else if (mode == 2) {
this.editMode = EditMode.READONLY;
} else {
throw new IllegalStateException("unknown mode " + mode);
}
}
}