blob: 35898e82840007fcc8482f8ef807035831c0d8d4 [file] [log] [blame]
/*
* Copyright (c) 2010-2021 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
package org.eclipse.scout.sdk.core.s.dto;
import org.eclipse.scout.sdk.core.generator.method.IMethodGenerator;
import org.eclipse.scout.sdk.core.generator.type.ITypeGenerator;
import org.eclipse.scout.sdk.core.model.api.Flags;
import org.eclipse.scout.sdk.core.model.api.IJavaEnvironment;
import org.eclipse.scout.sdk.core.model.api.IType;
import org.eclipse.scout.sdk.core.model.api.PropertyBean;
import org.eclipse.scout.sdk.core.s.annotation.FormDataAnnotationDescriptor;
import org.eclipse.scout.sdk.core.s.dto.form.FormDataGenerator;
import org.eclipse.scout.sdk.core.s.dto.table.TableFieldDataGenerator;
import org.eclipse.scout.sdk.core.s.dto.table.TableRowDataGenerator;
import org.eclipse.scout.sdk.core.s.generator.method.ScoutMethodGenerator;
import org.eclipse.scout.sdk.core.util.Strings;
/**
* <h3>{@link CompositeFormDataGenerator}</h3>
*
* @since 3.10.0 2013-08-27
*/
public class CompositeFormDataGenerator<TYPE extends CompositeFormDataGenerator<TYPE>> extends FormDataGenerator<TYPE> {
public CompositeFormDataGenerator(IType modelType, FormDataAnnotationDescriptor formDataAnnotation, IJavaEnvironment targetEnv) {
super(modelType, formDataAnnotation, targetEnv);
}
@Override
protected void setupBuilder() {
processInnerTypes(modelType());
super.setupBuilder();
}
protected void processInnerTypes(IType compositeType) {
var scoutApi = scoutApi();
// step into inner form field
compositeType.innerTypes()
.withFlags(Flags.AccPublic)
.withInstanceOf(scoutApi.IFormField()).stream()
.forEach(this::processFormField);
// step into formFieldMenus (special menu that may contain more form fields)
compositeType.innerTypes()
.withFlags(Flags.AccPublic)
.withInstanceOf(scoutApi.IFormFieldMenu()).stream()
.forEach(this::processInnerTypes);
// step into inner extensions
compositeType.innerTypes()
.withInstanceOf(scoutApi.ICompositeFieldExtension()).stream()
.forEach(this::processInnerTypes);
// step into inner table extensions of table-fields
compositeType.innerTypes()
.withRecursiveInnerTypes(true)
.withInstanceOf(scoutApi.ITableExtension()).stream()
.forEach(this::processTableExtension);
}
protected void processFormField(IType formField) {
var scoutApi = scoutApi();
var fieldAnnotation = FormDataAnnotationDescriptor.of(formField);
if (FormDataAnnotationDescriptor.isIgnore(fieldAnnotation)) {
return;
}
var fieldExtendsTemplateField = false;
var isCompositeField = formField.isInstanceOf(scoutApi.ICompositeField());
if (FormDataAnnotationDescriptor.isCreate(fieldAnnotation)) {
var formDataType = fieldAnnotation.getFormDataType();
String formDataTypeName;
if (formDataType == null) {
formDataTypeName = removeFieldSuffix(formField.elementName());
}
else {
formDataTypeName = formDataType.elementName();
}
ITypeGenerator<?> dtoGenerator;
if (fieldAnnotation.getSuperType().isInstanceOf(scoutApi.AbstractTableFieldBeanData())) {
// fill table bean
dtoGenerator = new TableFieldDataGenerator<>(formField, fieldAnnotation, targetEnvironment());
}
else if (isCompositeField && !formField.isInstanceOf(scoutApi.IValueField())) {
// field extends a field template.
fieldExtendsTemplateField = true;
dtoGenerator = new CompositeFormDataGenerator<>(formField, fieldAnnotation, targetEnvironment());
}
else {
dtoGenerator = new FormDataGenerator<>(formField, fieldAnnotation, targetEnvironment());
// special case if a property has the same name as a form field -> show warning
methods()
.filter(msb -> hasSimilarNameAs(msb, formDataTypeName))
.findAny()
.ifPresent(msb -> dtoGenerator.withComment(b -> b.appendTodo("Duplicate names '" + formDataTypeName + "'. Rename property or form field.")));
}
// Scout RT requires the first char to be upper-case for a getter.
// See org.eclipse.scout.rt.platform.reflect.FastBeanUtility.BEAN_METHOD_PAT.
var methodName = Strings.ensureStartWithUpperCase(formDataTypeName).toString();
this
.withType(dtoGenerator.withElementName(formDataTypeName), DtoMemberSortObjectFactory.forTypeFormDataFormField(formDataTypeName))
.withMethod(ScoutMethodGenerator.create()
.asPublic()
.withElementName(PropertyBean.GETTER_PREFIX + methodName)
.withReturnType(formDataTypeName)
.withBody(b -> b.returnClause().appendGetFieldByClass(formDataTypeName).semicolon()),
DtoMemberSortObjectFactory.forMethodFormDataFormField(methodName));
}
if (isCompositeField && !fieldExtendsTemplateField) {
processInnerTypes(formField);
}
}
/**
* @return {@code true} if the given {@link IMethodGenerator} has the same method name as a getter for the given
* formDataTypeName would have.
*/
protected boolean hasSimilarNameAs(IMethodGenerator<?, ?> msb, String formDataTypeName) {
var dataType = msb.returnType()
.flatMap(af -> af.apply(this.targetEnvironment()))
.get();
var name = PropertyBean.getterPrefixFor(dataType) + formDataTypeName;
return name.equals(msb.elementName().get());
}
protected void processTableExtension(IType tableExtension) {
withType(new TableRowDataGenerator<>(tableExtension, tableExtension, targetEnvironment())
.withElementName(getRowDataName(tableExtension.elementName()))
.withExtendsAnnotationIfNecessary(tableExtension),
DtoMemberSortObjectFactory.forTypeTableRowData(tableExtension.elementName()));
}
}