/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.webui.form; import com.vaadin.data.Validator; import com.vaadin.terminal.StreamResource; import com.vaadin.ui.Field; import com.vaadin.ui.Form; import com.vaadin.ui.Label; import com.vaadin.ui.VerticalLayout; import org.apache.commons.lang.StringUtils; import ru.codeinside.gses.activiti.forms.api.values.FormValue; import ru.codeinside.gses.activiti.forms.api.values.PropertyValue; import ru.codeinside.gses.activiti.forms.values.Block; import ru.codeinside.gses.vaadin.JsonFormIntegration; import ru.codeinside.gses.webui.ActivitiApp; import ru.codeinside.gses.webui.form.api.FieldValuesSource; import ru.codeinside.gses.webui.wizard.ExpandRequired; import java.io.Serializable; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; // типы: // string // multiline // long // date (+format) // masked (+format) // boolean // enum (+map) // directory (+service) // attachment // - signature // - smevRequest // enclosure == attachment // - smevRequestEnclosure // - smevResponseEnclosure // json final public class EForm extends Form implements AsyncCompletable, ExpandRequired, FieldValuesSource { final eform.Form form; final Map<String, EField> fields = new LinkedHashMap<String, EField>(); AsyncCompleter asyncCompleter; boolean hasAnyResult; JsonFormIntegration integration; String lastError; Long serial; FormValue formValue; public EForm(eform.Form form, FormValue formValue) { super(new VerticalLayout()); this.form = form; this.formValue = formValue; setSizeFull(); setImmediate(true); } @Override public Field getField(Object propertyId) { return fields.get(propertyId); } @Override public void attach() { ActivitiApp app = (ActivitiApp) getApplication(); hasAnyResult = false; if (serial == null) { serial = app.nextId(); putFields(formValue.getPropertyValues()); } app.getForms().put(serial, form); VerticalLayout layout = (VerticalLayout) getLayout(); try { integration = createIntegration(); integration.setSizeFull(); integration.setImmediate(true); layout.setSizeFull(); layout.addComponent(integration); layout.setExpandRatio(integration, 1f); layout.setImmediate(true); integration.setErrorReceiver(new ErrorReceiver()); integration.setValueReceiver(new ValueReceiver()); } catch (RuntimeException e) { Logger.getLogger(getClass().getName()).log(Level.WARNING, "ошибка загрузки шаблона", e); layout.addComponent(new Label("Ошибка загрузки формы ввода данных " + e.getLocalizedMessage())); } super.attach(); } private void putFields(List<PropertyValue<?>> propertyValues) { for (PropertyValue propertyValue : propertyValues) { fields.put(propertyValue.getId(), new EField(propertyValue.getId(), form.getProperty(propertyValue.getId()), propertyValue.getNode())); if (propertyValue instanceof Block) { for (List<PropertyValue<?>> clones : ((Block) propertyValue).getClones()) { putFields(clones); } } } } @Override public void detach() { VerticalLayout layout = (VerticalLayout) getLayout(); if (integration != null) { layout.removeAllComponents(); integration = null; } if (serial != null) { ActivitiApp app = (ActivitiApp) getApplication(); app.getForms().remove(serial); } super.detach(); } public List<FormField> getFormFields() { return new ArrayList<FormField>(fields.values()); } @Override public void commit() throws SourceException, Validator.InvalidValueException { if (lastError != null) { String msg = "Сбой " + lastError; lastError = null; hasAnyResult = false; throw new Validator.InvalidValueException(msg); } if (!hasAnyResult) { throw new Validator.InvalidValueException("Результат не получен!"); } } @Override public boolean isAsyncRequiredForComplete(AsyncCompleter asyncCompleter) { if (hasAnyResult) { return false; } if (asyncCompleter != null) { this.asyncCompleter = asyncCompleter; } if (integration != null) { integration.fireJson(); } return true; } JsonFormIntegration createIntegration() { ActivitiApp app = (ActivitiApp) getApplication(); String template = JsonForm.loadTemplate(app, formValue.getFormDefinition().getFormKey()); StreamResource.StreamSource htmlStreamSource = new JsonForm.InMemoryResource(template); StreamResource resource = new StreamResource(htmlStreamSource, "form-" + serial + "-" + System.currentTimeMillis() + ".html", app); resource.setCacheTime(0); JsonFormIntegration integration = new JsonFormIntegration(); integration.setSource(resource); integration.setSizeFull(); integration.setImmediate(true); integration.setValidationMode(true); return integration; } @Override public Map<String, Object> getFieldValues() { Map<String, Object> values = new LinkedHashMap<String, Object>(); for (EField eField : fields.values()) { if (eField.node.isFieldWritable()) { values.put(eField.id, eField.getValue()); } } return values; } final class ErrorReceiver implements JsonFormIntegration.Receiver, Serializable { @Override public void onReceive(String value) { hasAnyResult = true; lastError = JsonForm.simplifyErrorStack(value); asyncCompleter.onComplete(false); } } final class ValueReceiver implements JsonFormIntegration.Receiver, Serializable { @Override public void onReceive(String value) { value = StringUtils.trimToEmpty(value); hasAnyResult = Boolean.valueOf(value); lastError = null; if (hasAnyResult) { asyncCompleter.onComplete(true); } } } }