/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.workbench.common.forms.dynamic.client.helper; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import org.jboss.errai.databinding.client.MapPropertyType; import org.jboss.errai.databinding.client.PropertyType; import org.jboss.errai.databinding.client.api.DataBinder; import org.jboss.errai.ioc.client.container.IOC; import org.kie.workbench.common.forms.dynamic.service.shared.impl.MapModelRenderingContext; import org.kie.workbench.common.forms.fields.shared.AbstractFieldDefinition; import org.kie.workbench.common.forms.fields.shared.fieldTypes.relations.multipleSubform.definition.MultipleSubFormFieldDefinition; import org.kie.workbench.common.forms.fields.shared.fieldTypes.relations.subForm.definition.SubFormFieldDefinition; import org.kie.workbench.common.forms.model.FormDefinition; @ApplicationScoped public class MapModelBindingHelper { protected Map<Class<? extends AbstractFieldDefinition>, PropertyGenerator> propertiesGenerator = new HashMap<>(); protected Map<String, Class> basicProperties = new HashMap<>(); @PostConstruct public void initialize() { basicProperties.put(String.class.getName(), String.class); basicProperties.put(Integer.class.getName(), Integer.class); basicProperties.put(int.class.getName(), Integer.class); basicProperties.put(Double.class.getName(), Double.class); basicProperties.put(double.class.getName(), Double.class); basicProperties.put(Long.class.getName(), Long.class); basicProperties.put(long.class.getName(), Long.class); basicProperties.put(Float.class.getName(), Float.class); basicProperties.put(float.class.getName(), Float.class); basicProperties.put(Boolean.class.getName(), Boolean.class); basicProperties.put(boolean.class.getName(), Boolean.class); basicProperties.put(Character.class.getName(), Character.class); basicProperties.put(char.class.getName(), Character.class); basicProperties.put(Date.class.getName(), Date.class); basicProperties.put(BigInteger.class.getName(), BigInteger.class); basicProperties.put(BigDecimal.class.getName(), BigDecimal.class); IOC.getBeanManager().lookupBeans(PropertyGenerator.class).forEach(beanDef -> { PropertyGenerator generator = beanDef.getInstance(); propertiesGenerator.put(generator.getType(), generator); }); } public void initContext(MapModelRenderingContext context) { FormDefinition form = context.getRootForm(); Map<String, PropertyType> modelProperties = generateModelDefinition(form, context); Map<String, Object> content = DataBinder.forMap(modelProperties).getModel(); Map<String, Object> contextModel = context.getModel() != null ? context.getModel() : new HashMap<>(); prepareMapContent(content, form, contextModel, context); context.setModel(content); } public void prepareMapContent(Map<String, Object> formData, FormDefinition form, Map<String, Object> contextData, MapModelRenderingContext context) { form.getFields().forEach(field -> { if (field.getBinding() == null || field.getBinding().isEmpty()) { return; } if (formData.containsKey(field.getBinding())) { return; } Object fieldValue = contextData.get(field.getBinding()); if (field instanceof SubFormFieldDefinition) { prepareMapContentFor((SubFormFieldDefinition) field, fieldValue, formData, context); } else if (field instanceof MultipleSubFormFieldDefinition) { prepareMapContentFor((MultipleSubFormFieldDefinition) field, fieldValue, formData, context); } else { formData.put(field.getBinding(), fieldValue); } }); } protected void prepareMapContentFor(SubFormFieldDefinition field, Object fieldValue, Map<String, Object> formData, MapModelRenderingContext context) { FormDefinition subForm = context.getAvailableForms().get(field.getNestedForm()); formData.put(field.getBinding(), new HashMap<>()); Map<String, Object> nestedFormValues = (Map<String, Object>) formData.get(field.getBinding()); Map<String, Object> nestedValues = (Map<String, Object>) fieldValue; if (nestedValues == null) { nestedValues = new HashMap<>(); } prepareMapContent(nestedFormValues, subForm, nestedValues, context); } protected void prepareMapContentFor(MultipleSubFormFieldDefinition field, Object fieldValue, Map<String, Object> formData, MapModelRenderingContext context) { formData.put(field.getBinding(), new ArrayList<Map<String, Object>>()); final List<Map<String, Object>> nestedFormValues = (List<Map<String, Object>>) formData.get(field.getBinding()); final List<Map<String, Object>> nestedValues = (List<Map<String, Object>>) fieldValue; if (nestedValues != null) { nestedValues.forEach(nestedValue -> { Map<String, Object> nestedFormValue = new HashMap<>(); FormDefinition creationForm = context.getAvailableForms().get(field.getCreationForm()); prepareMapContent(nestedFormValue, creationForm, nestedValue, context); FormDefinition editionForm = context.getAvailableForms().get(field.getEditionForm()); prepareMapContent(nestedFormValue, editionForm, nestedValue, context); nestedFormValues.add(nestedFormValue); }); } } protected Map<String, PropertyType> generateModelDefinition(FormDefinition form, MapModelRenderingContext context) { return generateModelDefinition(form, context, new HashMap<>()); } protected Map<String, PropertyType> generateModelDefinition(FormDefinition form, MapModelRenderingContext context, Map<String, Map<String, PropertyType>> availableModels) { if (availableModels.containsKey(form.getId())) { return availableModels.get(form.getId()); } Map<String, PropertyType> formTypes = new HashMap<>(); availableModels.put(form.getId(), formTypes); form.getFields().forEach(field -> { PropertyType propertyType = null; if (basicProperties.containsKey(field.getStandaloneClassName())) { propertyType = new PropertyType(basicProperties.get(field.getStandaloneClassName())); } else if (propertiesGenerator.containsKey(field.getClass())) { PropertyGenerator generator = propertiesGenerator.get(field.getClass()); propertyType = generator.generatePropertyType(field); } else if (field instanceof SubFormFieldDefinition) { propertyType = getModeldefinitionFor((SubFormFieldDefinition) field, context, availableModels); } else if (field instanceof MultipleSubFormFieldDefinition) { propertyType = new PropertyType(List.class); } if (propertyType != null) { formTypes.put(field.getBinding(), propertyType); } }); return formTypes; } public MapPropertyType getModeldefinitionFor(SubFormFieldDefinition subFormField, MapModelRenderingContext context, Map<String, Map<String, PropertyType>> availableModels) { FormDefinition subForm = context.getAvailableForms().get(subFormField.getNestedForm()); return new MapPropertyType(generateModelDefinition(subForm, context, availableModels)); } public MapPropertyType getModeldefinitionFor(MultipleSubFormFieldDefinition subFormField, MapModelRenderingContext context, Map<String, Map<String, PropertyType>> availableModels) { FormDefinition creationForms = context.getAvailableForms().get(subFormField.getCreationForm()); Map<String, PropertyType> modelDefinition = generateModelDefinition(creationForms, context, availableModels); FormDefinition editionForm = context.getAvailableForms().get(subFormField.getCreationForm()); modelDefinition.putAll(generateModelDefinition(editionForm, context, availableModels)); modelDefinition.put(MapModelRenderingContext.FORM_ENGINE_OBJECT_IDX, new PropertyType(Integer.class)); modelDefinition.put(MapModelRenderingContext.FORM_ENGINE_EDITED_OBJECT, new PropertyType(Boolean.class)); return new MapPropertyType(modelDefinition); } }