package org.kie.workbench.common.forms.dynamic.client.rendering.renderers.relations.multipleSubform;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.TakesValue;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import org.jboss.errai.databinding.client.BindableProxy;
import org.jboss.errai.databinding.client.HasProperties;
import org.jboss.errai.ui.client.local.spi.TranslationService;
import org.jboss.errai.ui.shared.api.annotations.DataField;
import org.jboss.errai.ui.shared.api.annotations.Templated;
import org.kie.workbench.common.forms.crud.client.component.CrudActionsHelper;
import org.kie.workbench.common.forms.crud.client.component.CrudComponent;
import org.kie.workbench.common.forms.crud.client.component.formDisplay.FormDisplayer;
import org.kie.workbench.common.forms.crud.client.component.formDisplay.IsFormView;
import org.kie.workbench.common.forms.crud.client.resources.i18n.CrudComponentConstants;
import org.kie.workbench.common.forms.dynamic.client.DynamicFormRenderer;
import org.kie.workbench.common.forms.dynamic.client.rendering.renderers.relations.multipleSubform.binding.BindingHelper;
import org.kie.workbench.common.forms.dynamic.client.rendering.renderers.relations.multipleSubform.binding.BindingHelpers;
import org.kie.workbench.common.forms.dynamic.client.rendering.renderers.relations.multipleSubform.columns.ColumnGenerator;
import org.kie.workbench.common.forms.dynamic.service.shared.FormRenderingContext;
import org.kie.workbench.common.forms.dynamic.service.shared.RenderMode;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.relations.TableColumnMeta;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.relations.multipleSubform.definition.MultipleSubFormFieldDefinition;
import org.kie.workbench.common.forms.processing.engine.handling.FieldChangeHandler;
import org.kie.workbench.common.forms.processing.engine.handling.IsNestedModel;
import org.uberfire.ext.widgets.table.client.ColumnMeta;
@Templated
public class MultipleSubFormWidget extends Composite implements TakesValue<List<Object>>,
IsNestedModel {
public static final int PAGE_SIZE = 5;
@Inject
@DataField
private FlowPanel content;
protected ColumnGeneratorManager columnGeneratorManager;
protected DynamicFormRenderer formRenderer;
protected CrudComponent crudComponent;
protected TranslationService translationService;
private MultipleSubFormFieldDefinition field;
private FormRenderingContext renderingContext;
private AsyncDataProvider<HasProperties> dataProvider;
private FieldChangeHandler changeHandler;
private List<Object> values = null;
private List<HasProperties> tableValues = new ArrayList<>();
private BindingHelper bindingHelper;
protected boolean isReadOnly;
@Inject
public MultipleSubFormWidget(ColumnGeneratorManager columnGeneratorManager,
DynamicFormRenderer formRenderer,
CrudComponent crudComponent,
TranslationService translationService) {
this.columnGeneratorManager = columnGeneratorManager;
this.formRenderer = formRenderer;
this.crudComponent = crudComponent;
this.translationService = translationService;
}
protected void init() {
content.clear();
content.add(crudComponent);
}
protected void initCrud() {
final List<ColumnMeta> metas = new ArrayList<>();
HasProperties hasProperties = null;
try {
hasProperties = bindingHelper.getProxyDefinition();
} catch (Exception e) {
GWT.log("Unable to find proxy: " + e.getMessage());
}
for (TableColumnMeta meta : field.getColumnMetas()) {
String type = String.class.getName();
if (hasProperties != null) {
type = hasProperties.getBeanProperties().get(meta.getProperty()).getType().getName();
}
ColumnGenerator generator = columnGeneratorManager.getGeneratorByType(type);
if (generator != null) {
ColumnMeta<HasProperties> columnMeta = new ColumnMeta<HasProperties>(generator.getColumn(meta.getProperty()),
meta.getLabel());
metas.add(columnMeta);
}
}
dataProvider = new AsyncDataProvider<HasProperties>() {
@Override
protected void onRangeChanged(HasData<HasProperties> hasData) {
if (tableValues != null) {
updateRowCount(tableValues.size(),
true);
updateRowData(0,
tableValues);
} else {
updateRowCount(0,
true);
updateRowData(0,
new ArrayList<HasProperties>());
}
}
};
crudComponent.init(new CrudActionsHelper() {
@Override
public int getPageSize() {
return PAGE_SIZE;
}
@Override
public boolean showEmbeddedForms() {
return true;
}
@Override
public boolean isAllowCreate() {
return !isReadOnly;
}
@Override
public boolean isAllowEdit() {
return !isReadOnly;
}
@Override
public boolean isAllowDelete() {
return !isReadOnly;
}
@Override
public List<ColumnMeta> getGridColumns() {
return metas;
}
@Override
public AsyncDataProvider getDataProvider() {
return dataProvider;
}
public IsFormView<Object> getCreateInstanceForm() {
if (field.getCreationForm() != null) {
BindableProxy<?> proxy = bindingHelper.getNewProxy();
formRenderer.render(renderingContext.getCopyFor(field.getCreationForm(),
proxy));
return formRenderer;
}
return null;
}
public IsFormView<Object> getEditInstanceForm(int position) {
if (field.getEditionForm() != null) {
Object instance = bindingHelper.getProxyForModel(values.get(position));
formRenderer.render(renderingContext.getCopyFor(field.getCreationForm(),
instance));
return formRenderer;
}
return null;
}
@Override
public void createInstance() {
IsFormView form = getCreateInstanceForm();
crudComponent.displayForm(translationService.getTranslation(CrudComponentConstants.CrudComponentViewImplNewInstanceTitle),
form,
new FormDisplayer.FormDisplayerCallback() {
@Override
public void onCancel() {
}
@Override
public void onAccept() {
if (values == null) {
values = new ArrayList<>();
}
values.add(formRenderer.getModel());
tableValues.add((HasProperties) formRenderer.getModel());
refreshCrud();
fireFieldChange();
}
});
}
@Override
public void editInstance(int index) {
IsFormView form = getEditInstanceForm(index);
crudComponent.displayForm(translationService.getTranslation(CrudComponentConstants.CrudComponentViewImplEditInstanceTitle),
form,
new FormDisplayer.FormDisplayerCallback() {
@Override
public void onCancel() {
}
@Override
public void onAccept() {
bindingHelper.afterEdit((BindableProxy) formRenderer.getModel());
values.set(index,
formRenderer.getModel());
tableValues.set(index,
(HasProperties) formRenderer.getModel());
refreshCrud();
fireFieldChange();
}
});
}
@Override
public void deleteInstance(int index) {
values.remove(index);
tableValues.remove(index);
refreshCrud();
fireFieldChange();
}
});
initValues();
}
protected void initValues() {
tableValues.clear();
if (values != null) {
for (Object value : values) {
HasProperties tableValue;
if (value instanceof HasProperties) {
tableValue = (HasProperties) value;
} else {
tableValue = bindingHelper.getProxyForModel(value);
}
tableValues.add(tableValue);
}
}
}
public void config(MultipleSubFormFieldDefinition field,
FormRenderingContext renderingContext) {
init();
this.field = field;
this.renderingContext = renderingContext;
isReadOnly = field.getReadOnly() || !renderingContext.getRenderMode().equals(RenderMode.EDIT_MODE);
bindingHelper = BindingHelpers.getHelper(renderingContext,
field);
initCrud();
}
protected void refreshCrud() {
int currentStart = crudComponent.getCurrentPage();
if (currentStart < 0) {
currentStart = 0;
} else if (currentStart <= tableValues.size()) {
currentStart -= PAGE_SIZE;
}
dataProvider.updateRowCount(tableValues.size(),
true);
dataProvider.updateRowData(currentStart,
tableValues);
crudComponent.refresh();
}
@Override
public void setValue(List<Object> objects) {
// Avoid setting value via errai-data-binding when list is updated.
if (values != null) {
return;
}
values = objects;
initValues();
refreshCrud();
}
@Override
public List<Object> getValue() {
return values;
}
@Override
public void addFieldChangeHandler(FieldChangeHandler handler) {
this.changeHandler = handler;
}
public void fireFieldChange() {
if (changeHandler != null) {
changeHandler.onFieldChange(field.getName(),
values);
}
}
public void setReadOnly(boolean readOnly) {
isReadOnly = readOnly;
init();
initCrud();
}
}