/*
* Copyright 2017 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.data.modeller.service.impl;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.workbench.common.forms.data.modeller.model.DataObjectFormModel;
import org.kie.workbench.common.forms.data.modeller.service.DataObjectFinderService;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.HasMaxLength;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.HasPlaceHolder;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.checkBox.definition.CheckBoxFieldDefinition;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.datePicker.definition.DatePickerFieldDefinition;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.decimalBox.definition.DecimalBoxFieldDefinition;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.integerBox.definition.IntegerBoxFieldDefinition;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.textBox.definition.CharacterBoxFieldDefinition;
import org.kie.workbench.common.forms.fields.shared.fieldTypes.basic.textBox.definition.TextBoxFieldDefinition;
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.fields.test.TestFieldManager;
import org.kie.workbench.common.forms.model.FieldDataType;
import org.kie.workbench.common.forms.model.FieldDefinition;
import org.kie.workbench.common.forms.service.FieldManager;
import org.kie.workbench.common.screens.datamodeller.backend.server.handler.JPADomainHandler;
import org.kie.workbench.common.screens.datamodeller.service.DataModelerService;
import org.kie.workbench.common.services.datamodeller.core.DataModel;
import org.kie.workbench.common.services.datamodeller.core.DataObject;
import org.kie.workbench.common.services.datamodeller.core.ObjectProperty;
import org.kie.workbench.common.services.datamodeller.core.PropertyType;
import org.kie.workbench.common.services.datamodeller.core.impl.DataModelImpl;
import org.kie.workbench.common.services.datamodeller.core.impl.PropertyTypeFactoryImpl;
import org.kie.workbench.common.services.shared.project.KieProjectService;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.uberfire.backend.vfs.Path;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class DataObjectFormModelHandlerTest {
private final String NESTED_CLASSNAME = "com.test.Address";
private DataModel dataModel;
private DataObject dataObject;
private DataObjectFormModelHandler handler;
private DataObjectFormModel formModel;
private FieldManager fieldManager = new TestFieldManager();
@Mock
private KieProjectService projectService;
@Mock
private DataModelerService dataModelerService;
@Mock
private Path path;
private DataObjectFinderService finderService;
@Before
public void setUp() throws Exception {
createModel();
DataModellerFieldGenerator dataModellerFieldGenerator = new DataModellerFieldGenerator(fieldManager);
finderService = new DataObjectFinderServiceImpl(projectService,
dataModelerService);
handler = new DataObjectFormModelHandler(finderService,
dataModellerFieldGenerator);
when(dataModelerService.loadModel(any())).thenReturn(dataModel);
List<DataObjectFormModel> formModels = finderService.getAvailableDataObjects(path);
formModel = formModels.get(0);
handler.init(formModel,
path);
}
@Test
public void dataTypesGenerateCorrectFieldDefinitions() {
//all possible types of data object fields - expected field types couples
Map<String, List<String>> expectedFieldTypes = new HashMap<>();
expectedFieldTypes.put(DecimalBoxFieldDefinition.class.getSimpleName(),
Arrays.asList(BigDecimal.class.getName(),
Double.class.getName(),
Float.class.getName(),
double.class.getName(),
float.class.getName()));
expectedFieldTypes.put(IntegerBoxFieldDefinition.class.getSimpleName(),
Arrays.asList(BigInteger.class.getName(),
Byte.class.getName(),
Integer.class.getName(),
Long.class.getName(),
Short.class.getName(),
byte.class.getName(),
int.class.getName(),
long.class.getName(),
short.class.getName()));
expectedFieldTypes.put(CheckBoxFieldDefinition.class.getSimpleName(),
Arrays.asList(Boolean.class.getName(),
boolean.class.getName()));
expectedFieldTypes.put(TextBoxFieldDefinition.class.getSimpleName(),
Arrays.asList(String.class.getName()));
expectedFieldTypes.put(CharacterBoxFieldDefinition.class.getSimpleName(),
Arrays.asList(Character.class.getName(),
char.class.getName()));
expectedFieldTypes.put(DatePickerFieldDefinition.class.getSimpleName(),
Collections.singletonList(Date.class.getName()));
//TODO: Update after JBPM-5911 is fixed (move date-types from SubFormFieldType to DatePickerFieldType)
expectedFieldTypes.put(SubFormFieldDefinition.class.getSimpleName(),
Arrays.asList(LocalDate.class.getName(),
LocalDateTime.class.getName(),
OffsetDateTime.class.getName(),
LocalTime.class.getName(),
NESTED_CLASSNAME));
expectedFieldTypes.put(MultipleSubFormFieldDefinition.class.getSimpleName(),
Collections.singletonList(NESTED_CLASSNAME));
List<FieldDefinition> formModelFields = handler.getAllFormModelFields();
formFieldsShouldNotBeGeneratedForPersistenceId(formModelFields);
listsOfBasicDataTypesShouldBeExcludedFromTheFormFields(formModelFields);
for (FieldDefinition field : formModelFields) {
String dataType = field.getStandaloneClassName();
String fieldDefinition = field.getClass().getSimpleName();
assertTrue(expectedFieldTypes.get(fieldDefinition).contains(dataType));
}
}
//JBPM-5718 reproducer
private void formFieldsShouldNotBeGeneratedForPersistenceId(List<FieldDefinition> formModelFields) {
assertNotNull(dataObject.getProperty("id"));
List<ObjectProperty> properties = finderService.getDataObjectProperties(formModel.getClassName(),
path);
properties.forEach(property -> assertNotEquals("id",
property.getName()));
assertEquals("Form field should be generated for every data field except of persistence id",
formModelFields.size(),
properties.size());
}
//JBPM-5912 reproducer, TODO: implement after JBPM-5912 is fixed
private void listsOfBasicDataTypesShouldBeExcludedFromTheFormFields(List<FieldDefinition> formModelFields) {
}
@Test
public void textBoxHasCorrectProperties() {
checkCommonProperties("String");
}
@Test
public void characterBoxHasCorrectProperties() {
checkCommonProperties("char");
}
@Test
public void integerBoxHasCorrectProperties() {
checkCommonProperties("Short");
}
@Test
public void decimalBoxHasCorrectProperties() {
checkCommonProperties("Double");
}
@Test
public void checkBoxHasCorrectProperties() {
checkCommonProperties("Boolean");
}
@Test
public void datePickerHasCorrectProperties() {
DatePickerFieldDefinition datePicker = (DatePickerFieldDefinition) checkCommonProperties("Date");
assertTrue(datePicker.getShowTime());
}
@Test
public void subformHasCorrectProperties() {
SubFormFieldDefinition subForm = (SubFormFieldDefinition) checkCommonProperties("address");
assertEquals("",
subForm.getNestedForm());
}
@Test
public void multipleSubformHasCorrectProperties() {
MultipleSubFormFieldDefinition multipleSubform = (MultipleSubFormFieldDefinition) checkCommonProperties("address list");
assertEquals("",
multipleSubform.getCreationForm());
assertEquals("",
multipleSubform.getEditionForm());
assertEquals(Collections.emptyList(),
multipleSubform.getColumnMetas());
}
private FieldDefinition checkCommonProperties(String dataFieldName) {
ObjectProperty dataField = dataObject.getProperty(dataFieldName);
FieldDefinition formField = handler.createFieldDefinition(dataFieldName);
String dataFieldClassName = dataField.getClassName();
FieldDataType fieldTypeInfo = formField.getFieldTypeInfo();
//test common properties
assertEquals(dataFieldClassName,
fieldTypeInfo.getType());
assertFalse(fieldTypeInfo.isEnum());
assertEquals(dataField.isMultiple(),
fieldTypeInfo.isList());
assertEquals(dataField.getName(),
formField.getLabel());
assertEquals(dataField.getName(),
formField.getBinding());
assertEquals(dataFieldClassName,
formField.getStandaloneClassName());
assertFalse(formField.getReadOnly());
assertFalse(formField.getRequired());
assertTrue(formField.getValidateOnChange());
//test interface specific properties
if (formField instanceof HasPlaceHolder) {
assertEquals(dataField.getName(),
((HasPlaceHolder) formField).getPlaceHolder());
}
if (formField instanceof HasMaxLength) {
long maxLength = ((HasMaxLength) formField).getMaxLength();
assertTrue(formField instanceof CharacterBoxFieldDefinition ? maxLength == 1 : maxLength == 100);
}
return formField;
}
private void createModel() {
dataModel = new DataModelImpl();
dataObject = dataModel.addDataObject("Person1");
//makeTheClassPersistable
Map<String, Object> params = new HashMap<String, Object>();
params.put("persistable",
true);
JPADomainHandler jpaDomainHandler = new JPADomainHandler();
jpaDomainHandler.setDefaultValues(dataObject,
params);
//add all base type properties
PropertyTypeFactoryImpl propertyTypeFactory = new PropertyTypeFactoryImpl();
List<PropertyType> basePropertyTypes = propertyTypeFactory.getBasePropertyTypes();
for (PropertyType baseProperty : basePropertyTypes) {
dataObject.addProperty(baseProperty.getName(),
baseProperty.getClassName());
}
//add data object property
dataObject.addProperty("address",
NESTED_CLASSNAME);
//add list of data objects
dataObject.addProperty("address list",
NESTED_CLASSNAME,
true);
}
}