/**
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 * 
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License 2.0 
 *  which accompanies this distribution, and is available at
 *  https://www.eclipse.org/legal/epl-2.0/
 *
 *  SPDX-License-Identifier: EPL-2.0
 * 
 *  Contributors:
 * 	   Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
 * 
 * 
 *  This copyright notice shows up in the generated Java code
 */
package org.eclipse.osbp.autowirehelper;

import com.google.common.base.Objects;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.osbp.autowirehelper.JvmTypeProperties;
import org.eclipse.osbp.autowirehelper.utils.AutowireUtil;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.dsl.semantic.common.types.LDataType;
import org.eclipse.osbp.ecview.core.common.model.binding.BindingFactory;
import org.eclipse.osbp.ecview.core.common.model.binding.YBinding;
import org.eclipse.osbp.ecview.core.common.model.binding.YBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YBindingUpdateStrategy;
import org.eclipse.osbp.ecview.core.common.model.binding.YDetailValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YECViewModelListBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YECViewModelValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YListBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.binding.YValueBinding;
import org.eclipse.osbp.ecview.core.common.model.binding.YValueBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YAlignment;
import org.eclipse.osbp.ecview.core.common.model.core.YAlignmentContainer;
import org.eclipse.osbp.ecview.core.common.model.core.YAuthorizationable;
import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlot;
import org.eclipse.osbp.ecview.core.common.model.core.YBeanSlotListBindingEndpoint;
import org.eclipse.osbp.ecview.core.common.model.core.YDetailBeanSlot;
import org.eclipse.osbp.ecview.core.common.model.core.YEmbeddable;
import org.eclipse.osbp.ecview.core.common.model.core.YLayout;
import org.eclipse.osbp.ecview.core.common.model.core.YView;
import org.eclipse.osbp.ecview.core.common.model.visibility.YVisibilityProcessor;
import org.eclipse.osbp.ecview.core.extension.model.extension.util.SimpleExtensionModelFactory;
import org.eclipse.osbp.ecview.dsl.autowire.IAutowireDelegate;
import org.eclipse.osbp.ecview.dsl.derivedstate.UiModelDerivedStateComputerx;
import org.eclipse.osbp.ecview.dsl.extensions.BeanHelper;
import org.eclipse.osbp.ecview.dsl.extensions.BindableTypeResolver;
import org.eclipse.osbp.ecview.dsl.extensions.BindingInfoHelper;
import org.eclipse.osbp.ecview.dsl.extensions.OperationExtensions;
import org.eclipse.osbp.ecview.dsl.extensions.SuperTypeCollector;
import org.eclipse.osbp.ecview.dsl.extensions.TypeHelper;
import org.eclipse.osbp.ecview.extension.api.ILayoutingStrategy;
import org.eclipse.osbp.ecview.extension.model.YCollectionSuspect;
import org.eclipse.osbp.ecview.extension.model.YColumnInfo;
import org.eclipse.osbp.ecview.extension.model.YECviewFactory;
import org.eclipse.osbp.ecview.extension.model.YStrategyLayout;
import org.eclipse.osbp.ecview.extension.model.YSubTypeBaseSuspect;
import org.eclipse.osbp.ecview.extension.model.YSubTypeSuspect;
import org.eclipse.osbp.ecview.extension.model.YSuspect;
import org.eclipse.osbp.ecview.extension.model.YTypedCompoundSuspect;
import org.eclipse.osbp.ecview.extension.model.YTypedSuspect;
import org.eclipse.osbp.ecview.extension.model.visibility.YAuthorizationVisibilityProcessor;
import org.eclipse.osbp.ecview.extension.model.visibility.YVisibilityFactory;
import org.eclipse.osbp.ecview.semantic.uimodel.UiBeanSlot;
import org.eclipse.osbp.ecview.semantic.uimodel.UiBindingEndpointAssignment;
import org.eclipse.osbp.ecview.semantic.uimodel.UiBindingExpression;
import org.eclipse.osbp.ecview.semantic.uimodel.UiEmbeddable;
import org.eclipse.osbp.ecview.semantic.uimodel.UiHorizontalLayout;
import org.eclipse.osbp.ecview.semantic.uimodel.UiLayout;
import org.eclipse.osbp.ecview.semantic.uimodel.UiTypedBindable;
import org.eclipse.osbp.mobile.vaadin.ecview.model.VMSwitch;
import org.eclipse.osbp.mobile.vaadin.ecview.model.VMVerticalComponentGroup;
import org.eclipse.osbp.mobile.vaadin.ecview.model.VaadinMobileFactory;
import org.eclipse.osbp.runtime.common.annotations.DomainDescription;
import org.eclipse.osbp.runtime.common.annotations.DomainKey;
import org.eclipse.osbp.runtime.common.annotations.FilterDepth;
import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard;
import org.eclipse.osbp.runtime.common.annotations.UniqueEntry;
import org.eclipse.osbp.runtime.common.layouting.IPropertyConstants;
import org.eclipse.osbp.utils.functionnormalizer.api.FunctionTypingAPI;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.common.types.JvmAnnotationReference;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmField;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmPrimitiveType;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.JvmVoid;
import org.eclipse.xtext.common.types.TypesFactory;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.resource.IReferenceDescription;
import org.eclipse.xtext.ui.editor.findrefs.IReferenceFinder;
import org.eclipse.xtext.util.IAcceptor;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.StringExtensions;

@SuppressWarnings("restriction")
public class AutowireHelper implements IAutowireDelegate {
  public interface Layouter {
    public abstract void setup(final UiLayout uiRootLayout, final YLayout yRootLayout);
    
    public abstract void add(final YEmbeddable element);
    
    public abstract void add(final YSuspect suspect);
    
    public abstract void pushHierarchy(final YTypedCompoundSuspect suspect);
    
    public abstract void popHierarchy();
  }
  
  public static class MobileLayouter implements AutowireHelper.Layouter {
    private VMVerticalComponentGroup group;
    
    @Override
    public void setup(final UiLayout uiRootLayout, final YLayout yRootLayout) {
      this.group = VaadinMobileFactory.eINSTANCE.createVMVerticalComponentGroup();
      EList<YEmbeddable> _elements = yRootLayout.getElements();
      _elements.add(this.group);
    }
    
    @Override
    public void add(final YEmbeddable element) {
      this.group.addElement(element);
    }
    
    @Override
    public void add(final YSuspect ySuspect) {
    }
    
    @Override
    public void pushHierarchy(final YTypedCompoundSuspect suspect) {
      throw new UnsupportedOperationException("TODO: auto-generated method stub");
    }
    
    @Override
    public void popHierarchy() {
      throw new UnsupportedOperationException("TODO: auto-generated method stub");
    }
  }
  
  public static class StrategyLayoutLayouter implements AutowireHelper.Layouter {
    private Stack<YTypedCompoundSuspect> currentSubDtoSuspect = new Stack<YTypedCompoundSuspect>();
    
    private YStrategyLayout layout;
    
    @Override
    public void setup(final UiLayout uiRootLayout, final YLayout yRootLayout) {
      this.layout = YECviewFactory.eINSTANCE.createYStrategyLayout();
      this.layout.setId("strategyLayout");
      this.layout.setNumberColumns(uiRootLayout.getNumberColumns());
      yRootLayout.setNumberColumns(uiRootLayout.getNumberColumns());
      EList<YEmbeddable> _elements = yRootLayout.getElements();
      _elements.add(this.layout);
      EList<YVisibilityProcessor> _visibilityProcessors = yRootLayout.getView().getVisibilityProcessors();
      YAuthorizationVisibilityProcessor _createYAuthorizationVisibilityProcessor = YVisibilityFactory.eINSTANCE.createYAuthorizationVisibilityProcessor();
      _visibilityProcessors.add(_createYAuthorizationVisibilityProcessor);
      if ((yRootLayout instanceof YAlignmentContainer)) {
        ((YAlignmentContainer)yRootLayout).applyAlignment(this.layout, YAlignment.FILL_FILL);
      }
    }
    
    @Override
    public void add(final YEmbeddable element) {
    }
    
    @Override
    public void add(final YSuspect ySuspect) {
      boolean _isEmpty = this.currentSubDtoSuspect.isEmpty();
      boolean _not = (!_isEmpty);
      if (_not) {
        EList<YSuspect> _children = this.currentSubDtoSuspect.peek().getChildren();
        _children.add(ySuspect);
      } else {
        EList<YSuspect> _suspects = this.layout.getSuspects();
        _suspects.add(ySuspect);
      }
    }
    
    @Override
    public void pushHierarchy(final YTypedCompoundSuspect suspect) {
      this.currentSubDtoSuspect.push(suspect);
    }
    
    @Override
    public void popHierarchy() {
      this.currentSubDtoSuspect.pop();
    }
  }
  
  /**
   * The Class LocalResourceAccess.
   */
  public static class LocalResourceAccess implements IReferenceFinder.ILocalResourceAccess {
    private ResourceSet rs;
    
    public LocalResourceAccess(final ResourceSet rs) {
      this.rs = rs;
    }
    
    /**
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess
     * #readOnly(org.eclipse.emf.common.util.URI,
     * org.eclipse.xtext.util.concurrent.IUnitOfWork)
     */
    @Override
    public <R extends Object> R readOnly(final URI targetURI, final IUnitOfWork<R, ResourceSet> work) {
      try {
        return work.exec(this.rs);
      } catch (Throwable _e) {
        throw Exceptions.sneakyThrow(_e);
      }
    }
  }
  
  @Inject
  @Extension
  private TypeHelper _typeHelper;
  
  @Inject
  @Extension
  private AutowireUtil _autowireUtil;
  
  @Inject
  @Extension
  private IQualifiedNameProvider _iQualifiedNameProvider;
  
  @Inject
  private BindingInfoHelper bindingInfoHelper;
  
  @Inject
  private IReferenceFinder referenceFinder;
  
  private VaadinMobileFactory vFactory = VaadinMobileFactory.eINSTANCE;
  
  private UiModelDerivedStateComputerx computer;
  
  private boolean mobile;
  
  private YLayout yLayout;
  
  private UiLayout uiLayout;
  
  private AutowireHelper.Layouter layouter;
  
  private JvmDeclaredType beanType;
  
  private final SimpleExtensionModelFactory factory = new SimpleExtensionModelFactory();
  
  private YView yView;
  
  private YBeanSlot yMainBeanslot;
  
  @Override
  public void autowire(final UiLayout uiLayout, final UiModelDerivedStateComputerx computer, final boolean mobile) {
    boolean _isAutowire = uiLayout.isAutowire();
    boolean _not = (!_isAutowire);
    if (_not) {
      return;
    }
    this.computer = computer;
    this.mobile = mobile;
    this.uiLayout = uiLayout;
    this.yLayout = computer.<YLayout>associatedUi(uiLayout);
    this.yView = this.yLayout.getView();
    this.yMainBeanslot = this.getBeanSlot(uiLayout);
    boolean _matched = false;
    if (uiLayout instanceof UiHorizontalLayout) {
      _matched=true;
      AutowireHelper.Layouter _xifexpression = null;
      if ((!mobile)) {
        _xifexpression = new AutowireHelper.StrategyLayoutLayouter();
      } else {
        _xifexpression = new AutowireHelper.MobileLayouter();
      }
      this.layouter = _xifexpression;
      this.layouter.setup(uiLayout, this.yLayout);
    }
    if (!_matched) {
      return;
    }
    final BindableTypeResolver resolver = new BindableTypeResolver();
    JvmType resolvedType = resolver.resolveType(uiLayout.getAutoWireSource());
    if ((resolvedType instanceof JvmDeclaredType)) {
      this.beanType = ((JvmDeclaredType) resolvedType);
      final Map<String, OperationExtensions.OperationInfo> opInfoMap = OperationExtensions.getOperationInfos(this.beanType);
      final LinkedList<Map<String, OperationExtensions.OperationInfo>> sortedOpInfoMapList = this.createSortedMapList(opInfoMap);
      this.createSuspectStructure(sortedOpInfoMapList, this.beanType, mobile, null);
    }
  }
  
  /**
   * Finds all sub types of the beanType
   */
  public Set<URI> findSubTypes(final JvmType dtoType, final Resource resource) {
    Set<URI> _xblockexpression = null;
    {
      final Set<URI> result = CollectionLiterals.<URI>newHashSet();
      final Set<URI> jvmTypeURIs = CollectionLiterals.<URI>newHashSet();
      URI _uRI = EcoreUtil.getURI(dtoType);
      jvmTypeURIs.add(_uRI);
      final IAcceptor<IReferenceDescription> _function = (IReferenceDescription it) -> {
        final IReferenceDescription desc = it;
        EReference _eReference = desc.getEReference();
        boolean _tripleEquals = (_eReference == TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE);
        if (_tripleEquals) {
          boolean _endsWith = it.getSourceEObjectUri().fragment().endsWith("/@superTypes.0");
          if (_endsWith) {
            final URI uri = desc.getSourceEObjectUri();
            URI _createURI = URI.createURI(uri.toString().replace("/@superTypes.0", ""));
            result.add(_createURI);
          }
        }
      };
      final IAcceptor<IReferenceDescription> acceptor = _function;
      ResourceSet _resourceSet = resource.getResourceSet();
      AutowireHelper.LocalResourceAccess _localResourceAccess = new AutowireHelper.LocalResourceAccess(_resourceSet);
      this.referenceFinder.findAllReferences(jvmTypeURIs, _localResourceAccess, acceptor, null);
      _xblockexpression = result;
    }
    return _xblockexpression;
  }
  
  public YBeanSlot getBeanSlot(final UiLayout uiLayout) {
    UiBindingExpression autoWireSourceTemp = uiLayout.getAutoWireSource();
    if ((autoWireSourceTemp instanceof UiBindingEndpointAssignment)) {
      UiTypedBindable alias = ((UiBindingEndpointAssignment) autoWireSourceTemp).getTypedBindableAlias();
      if ((alias instanceof UiBeanSlot)) {
        return this.computer.<YBeanSlot>associatedUi(((UiBeanSlot) alias));
      }
    }
    return null;
  }
  
  public void createSuspectStructure(final JvmDeclaredType type, final boolean mobile, final YTypedCompoundSuspect parentSuspect) {
    final Map<String, OperationExtensions.OperationInfo> opInfoMap = OperationExtensions.getOperationInfos(type);
    final LinkedList<Map<String, OperationExtensions.OperationInfo>> sortedOpInfoMapList = this.createSortedMapList(opInfoMap);
    this.createSuspectStructure(sortedOpInfoMapList, type, mobile, parentSuspect);
  }
  
  public void createSuspectStructure(final LinkedList<Map<String, OperationExtensions.OperationInfo>> sortedOpInfoMapList, final JvmDeclaredType dtoType, final boolean mobile, final YTypedCompoundSuspect parentSuspect) {
    boolean _isEnum = this._typeHelper.isEnum(dtoType);
    boolean _not = (!_isEnum);
    if (_not) {
      final Consumer<Map<String, OperationExtensions.OperationInfo>> _function = (Map<String, OperationExtensions.OperationInfo> it) -> {
        this.createSuspectStructure(it, dtoType, mobile, parentSuspect);
      };
      sortedOpInfoMapList.forEach(_function);
    }
    final Set<URI> subTypeURIs = this.findSubTypes(dtoType, this.uiLayout.eResource());
    boolean _isEmpty = subTypeURIs.isEmpty();
    boolean _not_1 = (!_isEmpty);
    if (_not_1) {
      final YSubTypeBaseSuspect subtypeRootSuspect = YECviewFactory.eINSTANCE.createYSubTypeBaseSuspect();
      EList<String> _tags = subtypeRootSuspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__SUBTYPES_ROOT);
      subtypeRootSuspect.setTypeQualifiedName(dtoType.getQualifiedName());
      this.layouter.add(subtypeRootSuspect);
      this.layouter.pushHierarchy(subtypeRootSuspect);
    }
    final Consumer<URI> _function_1 = (URI it) -> {
      EObject _eObject = this.uiLayout.eResource().getResourceSet().getEObject(it, true);
      final JvmDeclaredType subDtoJvmType = ((JvmDeclaredType) _eObject);
      this.createSubTypeDtoSuspect(subDtoJvmType);
    };
    subTypeURIs.forEach(_function_1);
    boolean _isEmpty_1 = subTypeURIs.isEmpty();
    boolean _not_2 = (!_isEmpty_1);
    if (_not_2) {
      this.layouter.popHierarchy();
    }
  }
  
  public void createSuspectStructure(final Map<String, OperationExtensions.OperationInfo> opInfoMap, final JvmDeclaredType dtoType, final boolean mobile, final YTypedCompoundSuspect parentSuspect) {
    final Function1<OperationExtensions.OperationInfo, Boolean> _function = (OperationExtensions.OperationInfo it) -> {
      boolean _isDatabaseInfo = it.isDatabaseInfo();
      return Boolean.valueOf((!_isDatabaseInfo));
    };
    final Consumer<OperationExtensions.OperationInfo> _function_1 = (OperationExtensions.OperationInfo it) -> {
      JvmType type = null;
      try {
        type = it.getGetter().getReturnType().getType();
      } catch (final Throwable _t) {
        if (_t instanceof NullPointerException) {
          final NullPointerException e = (NullPointerException)_t;
          return;
        } else {
          throw Exceptions.sneakyThrow(_t);
        }
      }
      YSuspect suspect = null;
      ArrayList<AutowireUtil.Pair> properties = CollectionLiterals.<AutowireUtil.Pair>newArrayList();
      JvmField _field = it.getField();
      boolean _tripleNotEquals = (_field != null);
      if (_tripleNotEquals) {
        String _qualifiedName = it.getField().getDeclaringType().getQualifiedName();
        String _plus = (_qualifiedName + ".");
        String _name = it.getName();
        String _plus_1 = (_plus + _name);
        properties.addAll(this._autowireUtil.toProperties(dtoType, _plus_1));
      }
      if ((this._typeHelper.isBoolean(type) && (!it.isDirtyMark()))) {
        if (mobile) {
          this.createMobileSwitch(type, it);
        } else {
          suspect = this.createCheckbox(type, it);
        }
      } else {
        boolean _isNumberWithDigits = this._typeHelper.isNumberWithDigits(type);
        if (_isNumberWithDigits) {
          suspect = this.createDecimalField(type, it);
          boolean _isAttribute = this._autowireUtil.isAttribute(dtoType, it.getName(), "NumberToUomo");
          if (_isAttribute) {
            EList<String> _tags = suspect.getTags();
            _tags.add("NumberToUomo");
          } else {
            LDataType dataType = this._autowireUtil.toDataType(dtoType, it.getName());
            if ((dataType != null)) {
              String dataTypeName = dataType.getJvmTypeReference().getType().getIdentifier();
              boolean _equals = dataTypeName.equals(Double.class.getCanonicalName());
              if (_equals) {
                suspect = this.createCustomDecimalField(type, it);
              }
            }
          }
        } else {
          boolean _isNumberWithoutDigits = this._typeHelper.isNumberWithoutDigits(type);
          if (_isNumberWithoutDigits) {
            final Function1<AutowireUtil.Pair, Boolean> _function_2 = (AutowireUtil.Pair it_1) -> {
              return Boolean.valueOf(it_1.key.equals(IPropertyConstants.PROPERTY_KEY__FIELD_TYPE));
            };
            AutowireUtil.Pair _findFirst = IterableExtensions.<AutowireUtil.Pair>findFirst(properties, _function_2);
            String _value = null;
            if (_findFirst!=null) {
              _value=_findFirst.value;
            }
            final String fieldType = _value;
            if (((fieldType != null) && IterableExtensions.<AutowireUtil.Pair>exists(properties, ((Function1<AutowireUtil.Pair, Boolean>) (AutowireUtil.Pair it_1) -> {
              return Boolean.valueOf(fieldType.equalsIgnoreCase(IPropertyConstants.PROPERTY_SLIDER));
            })))) {
              suspect = this.createSlider(type, it, properties);
            } else {
              if ((((!it.isIdOrUUID()) && (!it.isVersion())) && (!it.isDirtyMark()))) {
                suspect = this.createNumberField(type, it);
              }
            }
          } else {
            boolean _isString = this._typeHelper.isString(type);
            if (_isString) {
              final Function1<AutowireUtil.Pair, Boolean> _function_3 = (AutowireUtil.Pair it_1) -> {
                return Boolean.valueOf(it_1.key.equals(IPropertyConstants.PROPERTY_KEY__FIELD_TYPE));
              };
              AutowireUtil.Pair _findFirst_1 = IterableExtensions.<AutowireUtil.Pair>findFirst(properties, _function_3);
              String _value_1 = null;
              if (_findFirst_1!=null) {
                _value_1=_findFirst_1.value;
              }
              final String fieldType_1 = _value_1;
              if ((((!it.isIdOrUUID()) && (!it.isVersion())) && (!it.isDirtyMark()))) {
                FunctionTypingAPI functionTypingAPI = new FunctionTypingAPI();
                final String functionImagePicker = functionTypingAPI.getFunctionImagePickerTypeName();
                if (((this.isDomainKey(it) || this.isDomainDescription(it)) || ((!StringExtensions.isNullOrEmpty(fieldType_1)) && fieldType_1.equals(IPropertyConstants.PROPERTY_SUGGESTTEXT)))) {
                  suspect = this.createSuggestTextField(type, it, opInfoMap);
                } else {
                  final Function1<AutowireUtil.Pair, Boolean> _function_4 = (AutowireUtil.Pair it_1) -> {
                    return Boolean.valueOf(it_1.key.toLowerCase().equals(IPropertyConstants.PROPERTY_BLOB));
                  };
                  boolean _exists = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_4);
                  if (_exists) {
                    suspect = this.createBlopUploadComponent(type, it);
                  } else {
                    if (((!StringExtensions.isNullOrEmpty(fieldType_1)) && fieldType_1.equals(IPropertyConstants.PROPERTY_RICH_TEXT))) {
                      suspect = this.createRichTextField(type, it);
                    } else {
                      if (((!StringExtensions.isNullOrEmpty(fieldType_1)) && fieldType_1.equals(IPropertyConstants.PROPERTY_MASKED_TEXT))) {
                        final Function1<AutowireUtil.Pair, Boolean> _function_5 = (AutowireUtil.Pair it_1) -> {
                          return Boolean.valueOf(it_1.key.equals(IPropertyConstants.PROPERTY_MASK));
                        };
                        AutowireUtil.Pair _findFirst_2 = IterableExtensions.<AutowireUtil.Pair>findFirst(properties, _function_5);
                        String _value_2 = null;
                        if (_findFirst_2!=null) {
                          _value_2=_findFirst_2.value;
                        }
                        final String mask = _value_2;
                        suspect = this.createMaskedTextField(type, it, mask);
                      } else {
                        if (((!StringExtensions.isNullOrEmpty(fieldType_1)) && fieldType_1.equals(IPropertyConstants.PROPERTY_PASSWORD))) {
                          suspect = this.createPasswordField(type, it);
                        } else {
                          final Function1<AutowireUtil.Pair, Boolean> _function_6 = (AutowireUtil.Pair it_1) -> {
                            return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_TEXTAREA));
                          };
                          boolean _exists_1 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_6);
                          if (_exists_1) {
                            suspect = this.createTextAreaField(type, it);
                          } else {
                            final Function1<AutowireUtil.Pair, Boolean> _function_7 = (AutowireUtil.Pair it_1) -> {
                              return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_ORGANIZATION));
                            };
                            boolean _exists_2 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_7);
                            if (_exists_2) {
                              suspect = this.createOrganizationComboBox(type, it);
                            } else {
                              final Function1<AutowireUtil.Pair, Boolean> _function_8 = (AutowireUtil.Pair it_1) -> {
                                return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_PERSPECTIVE));
                              };
                              boolean _exists_3 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_8);
                              if (_exists_3) {
                                suspect = this.createPerspectiveComboBox(type, it);
                              } else {
                                final Function1<AutowireUtil.Pair, Boolean> _function_9 = (AutowireUtil.Pair it_1) -> {
                                  return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_PRINTSERVICE));
                                };
                                boolean _exists_4 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_9);
                                if (_exists_4) {
                                  suspect = this.createPrintServiceComboBox(type, it);
                                } else {
                                  final Function1<AutowireUtil.Pair, Boolean> _function_10 = (AutowireUtil.Pair it_1) -> {
                                    return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_I18N));
                                  };
                                  boolean _exists_5 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_10);
                                  if (_exists_5) {
                                    suspect = this.createI18nComboBox(type, it);
                                  } else {
                                    final Function1<AutowireUtil.Pair, Boolean> _function_11 = (AutowireUtil.Pair it_1) -> {
                                      return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_THEME));
                                    };
                                    boolean _exists_6 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_11);
                                    if (_exists_6) {
                                      suspect = this.createThemeComboBox(type, it);
                                    } else {
                                      final Function1<AutowireUtil.Pair, Boolean> _function_12 = (AutowireUtil.Pair it_1) -> {
                                        return Boolean.valueOf(it_1.key.equalsIgnoreCase(IPropertyConstants.PROPERTY_MODEL));
                                      };
                                      boolean _exists_7 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_12);
                                      if (_exists_7) {
                                        suspect = this.createModelComboBox(type, it);
                                      } else {
                                        final Function1<AutowireUtil.Pair, Boolean> _function_13 = (AutowireUtil.Pair it_1) -> {
                                          return Boolean.valueOf(it_1.key.equalsIgnoreCase(functionImagePicker));
                                        };
                                        boolean _exists_8 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_13);
                                        if (_exists_8) {
                                          suspect = this.createIconComboBox(type, it);
                                        } else {
                                          suspect = this.createTextField(type, it);
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            } else {
              boolean _isDate = this._typeHelper.isDate(type);
              if (_isDate) {
                suspect = this.createDateField(type, it);
              } else {
                boolean _isEnum = this._typeHelper.isEnum(type);
                if (_isEnum) {
                  final Function1<AutowireUtil.Pair, Boolean> _function_14 = (AutowireUtil.Pair it_1) -> {
                    return Boolean.valueOf(it_1.key.toLowerCase().equals(IPropertyConstants.PROPERTY_OPTION_GROUP));
                  };
                  boolean _exists_9 = IterableExtensions.<AutowireUtil.Pair>exists(properties, _function_14);
                  if (_exists_9) {
                    suspect = this.createEnumOptionsGroup(type, it);
                  } else {
                    suspect = this.createEnumComboBox(type, it);
                  }
                } else {
                  boolean _isByteArray = this.isByteArray(type);
                  if (_isByteArray) {
                    final Function1<AutowireUtil.Pair, Boolean> _function_15 = (AutowireUtil.Pair it_1) -> {
                      return Boolean.valueOf(it_1.key.equals(IPropertyConstants.PROPERTY_KEY__FIELD_TYPE));
                    };
                    AutowireUtil.Pair _findFirst_3 = IterableExtensions.<AutowireUtil.Pair>findFirst(properties, _function_15);
                    String _value_3 = null;
                    if (_findFirst_3!=null) {
                      _value_3=_findFirst_3.value;
                    }
                    final String fieldType_2 = _value_3;
                    if (((!StringExtensions.isNullOrEmpty(fieldType_2)) && fieldType_2.equals(IPropertyConstants.PROPERTY_RICH_TEXT))) {
                      suspect = this.createRichTextField(type, it);
                    } else {
                      suspect = this.createBlopUploadComponent(type, it);
                    }
                  } else {
                    boolean _isDomainReference = this._typeHelper.isDomainReference(it);
                    if (_isDomainReference) {
                      suspect = this.createBeanReferenceField(type, it);
                    } else {
                      if (((it.getField() != null) && this._typeHelper.isCollection(it.getField()))) {
                        boolean _asGrid = it.asGrid();
                        if (_asGrid) {
                          suspect = this.createGrid(type, it);
                        } else {
                          boolean _asTable = it.asTable();
                          if (_asTable) {
                            suspect = this.createTableField(type, it);
                          }
                        }
                      } else {
                        boolean _isDto = this.isDto(type);
                        if (_isDto) {
                          suspect = this.createDtoSuspect(type, it);
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      if (((suspect != null) && it.isGroupMember())) {
        suspect.getTags().add(ILayoutingStrategy.TAG__GROUP);
        suspect.setGroupName(it.getGroupMemberName());
      }
      if ((parentSuspect == null)) {
        this.completeSuspect(type, it, suspect, dtoType);
      } else {
        this.completeSuspect(type, it, suspect, parentSuspect, dtoType);
      }
      for (final AutowireUtil.Pair keyAndValue : properties) {
        if ((suspect != null)) {
          suspect.getProperties().put(keyAndValue.key.toLowerCase(), keyAndValue.value);
        }
      }
    };
    IterableExtensions.<OperationExtensions.OperationInfo>filter(opInfoMap.values(), _function).forEach(_function_1);
  }
  
  public void createAuthorizationVisibilityProcessor(final YAuthorizationable element, final OperationExtensions.OperationInfo info) {
    JvmField _field = info.getField();
    boolean _tripleNotEquals = (_field != null);
    if (_tripleNotEquals) {
      EObject _eContainer = info.getField().eContainer();
      final JvmGenericType type = ((JvmGenericType) _eContainer);
      if (((!this._autowireUtil.isClass(info.getGetter().getReturnType().getType())) && this._autowireUtil.isAllowed(info.getGetter().getReturnType().getType(), type, info))) {
        element.setAuthorizationGroup(this._iQualifiedNameProvider.getFullyQualifiedName(type).toString());
        element.setAuthorizationId(info.getField().getSimpleName());
      }
    }
  }
  
  public YSuspect createDtoSuspect(final JvmType type, final OperationExtensions.OperationInfo info) {
    final YTypedCompoundSuspect dtoSuspect = YECviewFactory.eINSTANCE.createYTypedCompoundSuspect();
    EList<String> _tags = dtoSuspect.getTags();
    _tags.add(ILayoutingStrategy.TAG__DTO);
    if ((type instanceof JvmDeclaredType)) {
      this.createSuspectStructure(((JvmDeclaredType)type), false, dtoSuspect);
    }
    return dtoSuspect;
  }
  
  /**
   * A suspect that is created for each sub type of beanType.<br>
   * 1) we create a compound suspect<br>
   * 2) we add the compound suspect to the layout<br>
   * 3) we create a typed suspect for each operation info<br>
   * 4) we add the new typed suspect to the compound suspect and create a tree<br>
   */
  public YSuspect createSubTypeDtoSuspect(final JvmDeclaredType subDtoJvmType) {
    final YSubTypeSuspect subTypeSuspect = YECviewFactory.eINSTANCE.createYSubTypeSuspect();
    EList<String> _tags = subTypeSuspect.getTags();
    _tags.add(ILayoutingStrategy.TAG__SUBTYPE);
    subTypeSuspect.setTypeQualifiedName(subDtoJvmType.getQualifiedName());
    subTypeSuspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), subTypeSuspect.getTypeQualifiedName()));
    final YView view = this.computer.getCurrentView();
    final YDetailBeanSlot detailSlot = view.addDetailBeanSlot(subTypeSuspect.getTypeQualifiedName(), subTypeSuspect.getType(), 
      this.yMainBeanslot, "");
    EList<String> _tags_1 = detailSlot.getTags();
    _tags_1.add(ILayoutingStrategy.TAG__SUBTYPE);
    subTypeSuspect.setBeanSlot(detailSlot);
    this.layouter.add(subTypeSuspect);
    this.layouter.pushHierarchy(subTypeSuspect);
    final LinkedList<Map<String, OperationExtensions.OperationInfo>> subTypeInfos = this.createSortedMapList(OperationExtensions.getOperationInfos(subDtoJvmType, false));
    this.createSuspectStructure(subTypeInfos, subDtoJvmType, this.mobile, subTypeSuspect);
    this.layouter.popHierarchy();
    return subTypeSuspect;
  }
  
  /**
   * Returns true, if the type is a dto.
   */
  public boolean isDto(final JvmType type) {
    final SuperTypeCollector collector = new SuperTypeCollector();
    final Set<String> superTypes = collector.collectSuperTypeNames(type);
    return superTypes.contains(IDto.class.getName());
  }
  
  public void completeSuspect(final JvmType type, final OperationExtensions.OperationInfo info, final YSuspect suspect, final JvmType parentType) {
    if ((suspect != null)) {
      StringConcatenation _builder = new StringConcatenation();
      String _generateId = this._autowireUtil.generateId(this.uiLayout);
      _builder.append(_generateId);
      _builder.append(".");
      String _name = info.getName();
      _builder.append(_name);
      suspect.setId(_builder.toString());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags = suspect.getTags();
        _tags.add("readonly");
      }
      boolean _isOnKanbanCard = this.isOnKanbanCard(info);
      if (_isOnKanbanCard) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("onKanbanCard");
      }
      boolean _isUniqueEntry = this.isUniqueEntry(info);
      if (_isUniqueEntry) {
        EList<String> _tags_2 = suspect.getTags();
        _tags_2.add("unique");
        String[] splittedId = info.getId().split(":");
        int _length = splittedId.length;
        boolean _greaterThan = (_length > 1);
        if (_greaterThan) {
          String fqClassName = splittedId[0];
          suspect.getProperties().put("class", fqClassName);
        }
        suspect.getProperties().put("name", info.getName());
        this.createModelValueContainerBinding(suspect, info.getName(), type, "value");
      }
      boolean _isValidationConstraint = this.isValidationConstraint(info);
      if (_isValidationConstraint) {
        EList<String> _tags_3 = suspect.getTags();
        _tags_3.add("constraint");
        String[] splittedId_1 = info.getId().split(":");
        int _length_1 = splittedId_1.length;
        boolean _greaterThan_1 = (_length_1 > 1);
        if (_greaterThan_1) {
          String fqClassName_1 = splittedId_1[0];
          suspect.getProperties().put("class", fqClassName_1);
        }
        suspect.getProperties().put("name", info.getName());
      }
      this.layouter.add(suspect);
      if (((info.getField() != null) && this._typeHelper.isCollection(info.getField()))) {
        this.createModelListBinding(suspect, info, type, "list");
      } else {
        this.createModelValueBinding(suspect, info.getName(), type, "value", parentType);
      }
      if ((suspect instanceof YTypedCompoundSuspect)) {
        final YBindingEndpoint masterValueEP = ((YTypedCompoundSuspect)suspect).getValueBindingEndpoints().get(0);
        boolean _isEmpty = ((YTypedCompoundSuspect)suspect).getValueBindingEndpoints().isEmpty();
        boolean _not = (!_isEmpty);
        if (_not) {
          EList<YSuspect> _children = ((YTypedCompoundSuspect)suspect).getChildren();
          for (final YSuspect child : _children) {
            {
              String _id = ((YTypedCompoundSuspect)suspect).getId();
              String _id_1 = child.getId();
              String _plus = (_id + _id_1);
              child.setId(_plus);
              boolean _isEmpty_1 = child.getValueBindingEndpoints().isEmpty();
              boolean _not_1 = (!_isEmpty_1);
              if (_not_1) {
                final YBindingEndpoint childValueEP = child.getValueBindingEndpoints().get(0);
                if ((childValueEP instanceof YDetailValueBindingEndpoint)) {
                  YBindingEndpoint _copy = EcoreUtil.<YBindingEndpoint>copy(masterValueEP);
                  ((YDetailValueBindingEndpoint)childValueEP).setMasterObservable(((YValueBindingEndpoint) _copy));
                }
              }
            }
          }
        }
      }
      this.createAuthorizationVisibilityProcessor(suspect, info);
    }
  }
  
  public void completeSuspect(final JvmType type, final OperationExtensions.OperationInfo info, final YSuspect suspect, final YTypedCompoundSuspect parentSuspect, final JvmType parentType) {
    if ((suspect != null)) {
      StringConcatenation _builder = new StringConcatenation();
      String _id = parentSuspect.getId();
      _builder.append(_id);
      _builder.append(".");
      String _name = info.getName();
      _builder.append(_name);
      suspect.setId(_builder.toString());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags = suspect.getTags();
        _tags.add("readonly");
      }
      boolean _isValidationConstraint = this.isValidationConstraint(info);
      if (_isValidationConstraint) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("constraint");
        String[] splittedId = info.getId().split(":");
        int _length = splittedId.length;
        boolean _greaterThan = (_length > 1);
        if (_greaterThan) {
          String fqClassName = splittedId[0];
          suspect.getProperties().put("class", fqClassName);
        }
        suspect.getProperties().put("name", info.getName());
      }
      parentSuspect.getChildren().add(suspect);
      if (((info.getField() != null) && this._typeHelper.isCollection(info.getField()))) {
        this.createModelListBinding(suspect, info, type, "list");
      } else {
        this.createModelValueBinding(suspect, info.getName(), type, "value", parentType);
      }
      this.createAuthorizationVisibilityProcessor(suspect, info);
    }
  }
  
  /**
   * Sorted the attributes with the primitive types first and the rest after. Also all collections were left out.
   */
  public LinkedHashMap<String, OperationExtensions.OperationInfo> createSortedOpInfoMapForCollections(final Map<String, OperationExtensions.OperationInfo> opInfoMap) {
    LinkedHashMap<String, OperationExtensions.OperationInfo> _xblockexpression = null;
    {
      final LinkedHashMap<String, OperationExtensions.OperationInfo> sortedOpInfoList = CollectionLiterals.<String, OperationExtensions.OperationInfo>newLinkedHashMap();
      final LinkedHashMap<String, OperationExtensions.OperationInfo> nonPrimitiveOpInfoMap = CollectionLiterals.<String, OperationExtensions.OperationInfo>newLinkedHashMap();
      final BiConsumer<String, OperationExtensions.OperationInfo> _function = (String key, OperationExtensions.OperationInfo opInfo) -> {
        JvmType detailType = null;
        if (((opInfo.getField() != null) && (!this._typeHelper.isCollection(opInfo.getField())))) {
          detailType = opInfo.getGetter().getReturnType().getType();
          final boolean isPrimitive = ((detailType instanceof JvmPrimitiveType) || detailType.getQualifiedName().equals(
            String.class.getName()));
          if (isPrimitive) {
            sortedOpInfoList.put(key, opInfo);
          } else {
            nonPrimitiveOpInfoMap.put(key, opInfo);
          }
        }
      };
      opInfoMap.forEach(_function);
      sortedOpInfoList.putAll(nonPrimitiveOpInfoMap);
      _xblockexpression = sortedOpInfoList;
    }
    return _xblockexpression;
  }
  
  /**
   * Sorted the attributes in a individual but fix order.
   */
  public LinkedList<Map<String, OperationExtensions.OperationInfo>> createSortedMapList(final Map<String, OperationExtensions.OperationInfo> opInfoMap) {
    LinkedList<Map<String, OperationExtensions.OperationInfo>> _xblockexpression = null;
    {
      final LinkedList<Map<String, OperationExtensions.OperationInfo>> sortedOpInfoList = CollectionLiterals.<Map<String, OperationExtensions.OperationInfo>>newLinkedList();
      sortedOpInfoList.add(opInfoMap);
      _xblockexpression = sortedOpInfoList;
    }
    return _xblockexpression;
  }
  
  public boolean isDomainKey(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        boolean _equals = DomainKey.class.getCanonicalName().equals(annotationRefs.getAnnotation().getIdentifier());
        if (_equals) {
          return true;
        }
      }
    }
    return false;
  }
  
  public boolean isOnKanbanCard(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        boolean _equals = OnKanbanCard.class.getCanonicalName().equals(annotationRefs.getAnnotation().getIdentifier());
        if (_equals) {
          return true;
        }
      }
    }
    return false;
  }
  
  public boolean isDomainDescription(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        boolean _equals = DomainDescription.class.getCanonicalName().equals(annotationRefs.getAnnotation().getIdentifier());
        if (_equals) {
          return true;
        }
      }
    }
    return false;
  }
  
  public boolean isValidationConstraint(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        if (((annotationRefs.getAnnotation().getIdentifier() != null) && 
          annotationRefs.getAnnotation().getIdentifier().startsWith("javax.validation"))) {
          return true;
        }
      }
    }
    return false;
  }
  
  public boolean isUniqueEntry(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        if (((annotationRefs.getAnnotation().getIdentifier() != null) && 
          annotationRefs.getAnnotation().getIdentifier().equals(UniqueEntry.class.getCanonicalName()))) {
          return true;
        }
      }
    }
    return false;
  }
  
  public boolean isIndex(final OperationExtensions.OperationInfo info) {
    if (((info != null) && (info.getField() != null))) {
      EList<JvmAnnotationReference> _annotations = info.getField().getAnnotations();
      for (final JvmAnnotationReference annotationRefs : _annotations) {
        boolean _equals = DomainKey.class.getCanonicalName().equals(annotationRefs.getAnnotation().getIdentifier());
        if (_equals) {
          return true;
        }
      }
    }
    return false;
  }
  
  /**
   * Returns true, if the type is boolean
   * 
   * @param type
   * @return
   */
  public boolean isByteArray(final JvmType type) {
    if ((type == null)) {
      return false;
    }
    if ((this.isArray(type, Byte.class) || this.isArray(type, Byte.TYPE))) {
      return true;
    }
    return false;
  }
  
  public boolean isArray(final JvmType type, final Class<?> clazz) {
    if ((type == null)) {
      return false;
    }
    String className = clazz.getName();
    char _charAt = className.charAt(0);
    boolean _equals = Objects.equal(Character.valueOf(_charAt), "[");
    if (_equals) {
      className = clazz.getCanonicalName();
    }
    className = className.concat("[]");
    boolean result = className.equals(type.getIdentifier());
    return result;
  }
  
  public YTypedSuspect createTextField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__TEXT);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createSuggestTextField(final JvmType type, final OperationExtensions.OperationInfo info, final Map<String, OperationExtensions.OperationInfo> opInfoMap) {
    YTypedSuspect _xblockexpression = null;
    {
      final OperationExtensions.OperationInfo idAttInfo = this.getToIdInfo(opInfoMap.values());
      if ((idAttInfo == null)) {
        return this.createTextField(type, info);
      }
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__SUGGEST_TEXT);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), this.beanType.getQualifiedName()));
      suspect.setTypeQualifiedName(this.beanType.getQualifiedName());
      suspect.getProperties().put(IPropertyConstants.PROPERTY__ITEM_CAPTION, info.getName());
      suspect.getProperties().put(IPropertyConstants.PROPERTY__ITEM_FILTER, info.getName());
      suspect.getProperties().put(IPropertyConstants.PROPERTY__ITEM_UUID, idAttInfo.getName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  /**
   * Returns the operation info for the id property.
   */
  public OperationExtensions.OperationInfo getToIdInfo(final Collection<OperationExtensions.OperationInfo> infos) {
    for (final OperationExtensions.OperationInfo info : infos) {
      boolean _isIdOrUUID = info.isIdOrUUID();
      if (_isIdOrUUID) {
        return info;
      }
    }
    return null;
  }
  
  public YTypedSuspect createTextAreaField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__TEXTAREA);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createSlider(final JvmType type, final OperationExtensions.OperationInfo info, final ArrayList<AutowireUtil.Pair> pairs) {
    YTypedSuspect _xblockexpression = null;
    {
      final Function1<AutowireUtil.Pair, Boolean> _function = (AutowireUtil.Pair it) -> {
        return Boolean.valueOf(it.key.equals("min"));
      };
      AutowireUtil.Pair _findFirst = IterableExtensions.<AutowireUtil.Pair>findFirst(pairs, _function);
      String _value = null;
      if (_findFirst!=null) {
        _value=_findFirst.value;
      }
      final String minValue = ((String) _value);
      final Function1<AutowireUtil.Pair, Boolean> _function_1 = (AutowireUtil.Pair it) -> {
        return Boolean.valueOf(it.key.equals("max"));
      };
      AutowireUtil.Pair _findFirst_1 = IterableExtensions.<AutowireUtil.Pair>findFirst(pairs, _function_1);
      String _value_1 = null;
      if (_findFirst_1!=null) {
        _value_1=_findFirst_1.value;
      }
      final String maxValue = ((String) _value_1);
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__SLIDER);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      suspect.getProperties().put("min", minValue);
      suspect.getProperties().put("max", maxValue);
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createDecimalField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__DECIMAL);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createNumberField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__NUMBER);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createCheckbox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__BOOLEAN);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createDateField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__DATE);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createIconComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__IMAGE_PICKER);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createEnumComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__ENUM_COMBO);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createOrganizationComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__ORGANIZATION_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createPerspectiveComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__PERSPECTIVE_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createThemeComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__THEME_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createModelComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__MODEL_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createPrintServiceComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__PRINTSERVICE_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createI18nComboBox(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__I18N_COMBO);
      suspect.setType(String.class);
      suspect.setTypeQualifiedName(String.class.getName());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createEnumOptionsGroup(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__ENUM_OPTIONS);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      StringConcatenation _builder = new StringConcatenation();
      String _generateId = this._autowireUtil.generateId(this.uiLayout);
      _builder.append(_generateId);
      _builder.append(".");
      String _name = info.getName();
      _builder.append(_name);
      suspect.setId(_builder.toString());
      boolean _isReadonly = info.isReadonly();
      if (_isReadonly) {
        EList<String> _tags_1 = suspect.getTags();
        _tags_1.add("readonly");
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createBeanReferenceField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      YTypedSuspect suspect = null;
      Resource _eResource = null;
      if (this.uiLayout!=null) {
        _eResource=this.uiLayout.eResource();
      }
      ResourceSet _resourceSet = null;
      if (_eResource!=null) {
        _resourceSet=_eResource.getResourceSet();
      }
      String _qualifiedName = null;
      if (type!=null) {
        _qualifiedName=type.getQualifiedName();
      }
      Class<?> suspectType = this.computer.loadClass(_resourceSet, _qualifiedName);
      String captionProperty = BeanHelper.findCaptionProperty(suspectType);
      String captionDescription = BeanHelper.findDescriptionProperty(suspectType);
      if (((captionProperty != null) || (captionDescription != null))) {
        suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
        suspect.setType(suspectType);
        EList<String> _tags = suspect.getTags();
        _tags.add(ILayoutingStrategy.TAG__BEAN_REFERENCE);
        StringConcatenation _builder = new StringConcatenation();
        String _generateId = this._autowireUtil.generateId(this.uiLayout);
        _builder.append(_generateId);
        _builder.append(".");
        String _name = info.getName();
        _builder.append(_name);
        suspect.setId(_builder.toString());
        boolean _isReadonly = info.isReadonly();
        if (_isReadonly) {
          EList<String> _tags_1 = suspect.getTags();
          _tags_1.add("readonly");
        }
        boolean _hasAnnotation = info.hasAnnotation(FilterDepth.class);
        if (_hasAnnotation) {
          final int depth = this._autowireUtil.toFilterDepth(info.getField());
          suspect.getProperties().put(IPropertyConstants.PROPERTY__FILTER_DEPTH, Integer.toString(depth));
        }
        suspect.setTypeQualifiedName(type.getQualifiedName());
        suspect.getProperties().put(IPropertyConstants.PROPERTY__ITEM_CAPTION, captionProperty);
        suspect.getProperties().put(IPropertyConstants.PROPERTY__ITEM_DESCRIPTION, captionDescription);
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YTypedSuspect createTableField(final JvmType type, final OperationExtensions.OperationInfo info) {
    return this.createCollection(type, info, ILayoutingStrategy.TAG__TABLE);
  }
  
  public YTypedSuspect createGrid(final JvmType type, final OperationExtensions.OperationInfo info) {
    return this.createCollection(type, info, ILayoutingStrategy.TAG__GRID);
  }
  
  public YTypedSuspect createCollection(final JvmType type, final OperationExtensions.OperationInfo info, final String tag) {
    YCollectionSuspect _xblockexpression = null;
    {
      final YCollectionSuspect suspect = YECviewFactory.eINSTANCE.createYCollectionSuspect();
      JvmTypeReference _returnType = info.getGetter().getReturnType();
      final JvmParameterizedTypeReference collectionType = ((JvmParameterizedTypeReference) _returnType);
      final JvmTypeReference typeInCollection = collectionType.getArguments().get(0);
      try {
        suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), typeInCollection.getQualifiedName()));
      } catch (final Throwable _t) {
        if (_t instanceof NullPointerException) {
          final NullPointerException ex = (NullPointerException)_t;
          ex.printStackTrace();
          throw ex;
        } else {
          throw Exceptions.sneakyThrow(_t);
        }
      }
      EList<String> _tags = suspect.getTags();
      _tags.add(tag);
      suspect.setTypeQualifiedName(typeInCollection.getQualifiedName());
      JvmType _type = null;
      if (typeInCollection!=null) {
        _type=typeInCollection.getType();
      }
      if ((_type instanceof JvmDeclaredType)) {
        JvmType _type_1 = typeInCollection.getType();
        final JvmDeclaredType castedType = ((JvmDeclaredType) _type_1);
        final Map<String, List<AutowireUtil.Pair>> propMap = this._autowireUtil.toFieldProperties(castedType);
        final Map<String, OperationExtensions.OperationInfo> opInfoMap = OperationExtensions.getOperationInfos(castedType);
        final LinkedHashMap<String, OperationExtensions.OperationInfo> sortedOpInfoMap = this.createSortedOpInfoMapForCollections(opInfoMap);
        final Function1<OperationExtensions.OperationInfo, Boolean> _function = (OperationExtensions.OperationInfo it) -> {
          return Boolean.valueOf(((((!it.isDatabaseInfo()) && (!it.isIdOrUUID())) && (!it.isVersion())) && (!it.isDirtyMark())));
        };
        final Consumer<OperationExtensions.OperationInfo> _function_1 = (OperationExtensions.OperationInfo it) -> {
          JvmType detailType = it.getGetter().getReturnType().getType();
          YColumnInfo columnInfo = null;
          final boolean isPrimitive = (detailType instanceof JvmPrimitiveType);
          boolean _isDomainReference = this._typeHelper.isDomainReference(it);
          if (_isDomainReference) {
            Collection<JvmTypeProperties.Info> _values = JvmTypeProperties.getOperationInfos(((JvmDeclaredType) detailType)).values();
            for (final JvmTypeProperties.Info nestedInfo : _values) {
              boolean _hasAnnotation = nestedInfo.hasAnnotation(DomainKey.class);
              if (_hasAnnotation) {
                final Map<String, List<AutowireUtil.Pair>> nestPropMap = this._autowireUtil.toFieldProperties(((JvmDeclaredType) detailType));
                columnInfo = this.createYColumnInfo(nestedInfo.getType());
                String _simpleName = it.getField().getSimpleName();
                String _plus = (_simpleName + ".");
                String _attributePath = nestedInfo.getAttributePath();
                String _plus_1 = (_plus + _attributePath);
                columnInfo.setName(_plus_1);
                List<AutowireUtil.Pair> propList = nestPropMap.get(nestedInfo.getName());
                this.setYColumnInfoProperties(columnInfo, propList);
              }
            }
          } else {
            JvmType objectType = it.getField().getType().getType();
            if (isPrimitive) {
              final String primitiveTypeName = it.getField().getType().getType().getQualifiedName();
              JvmVoid _createJvmVoid = TypesFactory.eINSTANCE.createJvmVoid();
              final InternalEObject proxy = ((InternalEObject) _createJvmVoid);
              proxy.eSetProxyURI(URI.createURI(this.toObjectProxy(primitiveTypeName)));
              EObject _resolve = EcoreUtil.resolve(proxy, this.uiLayout.eResource());
              objectType = ((JvmType) _resolve);
            }
            columnInfo = this.createYColumnInfo(objectType);
            columnInfo.setName(it.getName());
            List<AutowireUtil.Pair> propList_1 = propMap.get(it.getField().getIdentifier());
            this.setYColumnInfoProperties(columnInfo, propList_1);
          }
          if ((columnInfo != null)) {
            columnInfo.setLabelI18nKey(columnInfo.getName());
            EList<YColumnInfo> _columns = suspect.getColumns();
            _columns.add(columnInfo);
          }
        };
        IterableExtensions.<OperationExtensions.OperationInfo>filter(sortedOpInfoMap.values(), _function).forEach(_function_1);
      }
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  /**
   * Creates a proxy object
   */
  public String toObjectProxy(final String primitiveTypeName) {
    if (primitiveTypeName != null) {
      switch (primitiveTypeName) {
        case "int":
          StringConcatenation _builder = new StringConcatenation();
          _builder.append("java:/Objects/java.lang.Integer#java.lang.Integer");
          return _builder.toString();
        default:
          StringConcatenation _builder_1 = new StringConcatenation();
          _builder_1.append("java:/Objects/java.lang.");
          String _firstUpper = StringExtensions.toFirstUpper(primitiveTypeName);
          _builder_1.append(_firstUpper);
          _builder_1.append("#java.lang.");
          String _firstUpper_1 = StringExtensions.toFirstUpper(primitiveTypeName);
          _builder_1.append(_firstUpper_1);
          return _builder_1.toString();
      }
    } else {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("java:/Objects/java.lang.");
      String _firstUpper = StringExtensions.toFirstUpper(primitiveTypeName);
      _builder_1.append(_firstUpper);
      _builder_1.append("#java.lang.");
      String _firstUpper_1 = StringExtensions.toFirstUpper(primitiveTypeName);
      _builder_1.append(_firstUpper_1);
      return _builder_1.toString();
    }
  }
  
  public void createMobileSwitch(final JvmType type, final OperationExtensions.OperationInfo info) {
    final VMSwitch yField = this.vFactory.createVMSwitch();
    boolean _isReadonly = info.isReadonly();
    boolean _not = (!_isReadonly);
    yField.setInitialEnabled(_not);
    yField.setLabel(info.getName());
    this.layouter.add(yField);
    this.createBinding(yField, info, type, "value");
  }
  
  public YSuspect createRichTextField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      boolean _isString = this._typeHelper.isString(type);
      if (_isString) {
        EList<String> _tags = suspect.getTags();
        _tags.add(ILayoutingStrategy.TAG__RICH_TEXT__STRING);
      } else {
        boolean _isByteArray = this.isByteArray(type);
        if (_isByteArray) {
          EList<String> _tags_1 = suspect.getTags();
          _tags_1.add(ILayoutingStrategy.TAG__RICH_TEXT__BLOB);
        } else {
          String _qualifiedName = type.getQualifiedName();
          String _plus = ("RichTextFields need to be bound to String or byte[]. " + _qualifiedName);
          String _plus_1 = (_plus + 
            " is not a valid option.");
          throw new IllegalArgumentException(_plus_1);
        }
      }
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YSuspect createMaskedTextField(final JvmType type, final OperationExtensions.OperationInfo info, final String mask) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__MASKED_TEXT_FIELD);
      suspect.getProperties().put(IPropertyConstants.PROPERTY_MASK, mask);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YSuspect createMaskedDecimalField(final JvmType type, final OperationExtensions.OperationInfo info, final String mask) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__MASKED_DECIMAL_FIELD);
      suspect.getProperties().put(IPropertyConstants.PROPERTY_MASK, mask);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YSuspect createPasswordField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      boolean _isString = this._typeHelper.isString(type);
      if (_isString) {
        EList<String> _tags = suspect.getTags();
        _tags.add(ILayoutingStrategy.TAG__PASSWORD);
      } else {
        String _qualifiedName = type.getQualifiedName();
        String _plus = ("PasswordField need to be bound to String. " + _qualifiedName);
        String _plus_1 = (_plus + " is not a valid option.");
        throw new IllegalArgumentException(_plus_1);
      }
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YSuspect createBlopUploadComponent(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__BLOB);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  public YSuspect createCustomDecimalField(final JvmType type, final OperationExtensions.OperationInfo info) {
    YTypedSuspect _xblockexpression = null;
    {
      final YTypedSuspect suspect = YECviewFactory.eINSTANCE.createYTypedSuspect();
      EList<String> _tags = suspect.getTags();
      _tags.add(ILayoutingStrategy.TAG__DECIMAL);
      suspect.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), type.getQualifiedName()));
      suspect.setTypeQualifiedName(type.getQualifiedName());
      _xblockexpression = suspect;
    }
    return _xblockexpression;
  }
  
  /**
   * Create the bindings and install at the view
   */
  public void createBinding(final YEmbeddable yField, final OperationExtensions.OperationInfo info, final JvmType type, final String fieldProperty) {
    UiBindingExpression _autoWireSource = this.uiLayout.getAutoWireSource();
    final UiBindingEndpointAssignment uiModelEndpoint = ((UiBindingEndpointAssignment) _autoWireSource);
    final YValueBindingEndpoint yModelEndpoint = this.computer.createValueBindingEndpoint(uiModelEndpoint);
    final YDetailValueBindingEndpoint detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint();
    detailValueEndpoint.setPropertyPath(info.getName());
    detailValueEndpoint.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), this.beanType.getQualifiedName()));
    final YECViewModelValueBindingEndpoint yFieldEndpoint = BindingFactory.eINSTANCE.createYECViewModelValueBindingEndpoint();
    yFieldEndpoint.setElement(yField);
    yFieldEndpoint.setPropertyPath(fieldProperty);
    yFieldEndpoint.setTypeQualifiedName(this.beanType.getQualifiedName());
    yFieldEndpoint.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), this.beanType.getQualifiedName()));
    if (((yFieldEndpoint.getType() != null) && yFieldEndpoint.getType().isAssignableFrom(EObject.class))) {
      yFieldEndpoint.setEmfNsURI(yField.eClass().getEPackage().getNsURI());
    }
    final YValueBinding yBinding = BindingFactory.eINSTANCE.createYValueBinding();
    yBinding.setTargetEndpoint(yFieldEndpoint);
    yBinding.setModelEndpoint(detailValueEndpoint);
    yBinding.setModelToTargetStrategy(YBindingUpdateStrategy.UPDATE);
    YBindingUpdateStrategy _xifexpression = null;
    boolean _isReadonly = info.isReadonly();
    if (_isReadonly) {
      _xifexpression = YBindingUpdateStrategy.NEVER;
    } else {
      _xifexpression = YBindingUpdateStrategy.UPDATE;
    }
    yBinding.setTargetToModelStrategy(_xifexpression);
    EList<YBinding> _bindings = this.yLayout.getView().getOrCreateBindingSet().getBindings();
    _bindings.add(yBinding);
    yField.setLabelI18nKey(detailValueEndpoint.getPropertyPath());
  }
  
  /**
   * Create the bindings and install at the view
   */
  public void createModelValueBinding(final YSuspect suspect, final String propertyPath, final JvmType type, final String fieldProperty, final JvmType parentType) {
    final YBeanSlot subTypeBeanSlot = this.findSubTypeBeanSlot(suspect);
    YValueBindingEndpoint endpoint = null;
    String path = "";
    if ((subTypeBeanSlot == null)) {
      UiBindingExpression _autoWireSource = this.uiLayout.getAutoWireSource();
      final UiBindingEndpointAssignment uiModelEndpoint = ((UiBindingEndpointAssignment) _autoWireSource);
      final YValueBindingEndpoint yModelEndpoint = this.computer.createValueBindingEndpoint(uiModelEndpoint);
      final YDetailValueBindingEndpoint detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint();
      detailValueEndpoint.setPropertyPath(propertyPath);
      detailValueEndpoint.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), 
        parentType.getQualifiedName()));
      endpoint = detailValueEndpoint;
      path = detailValueEndpoint.getPropertyPath();
    } else {
      endpoint = subTypeBeanSlot.createBindingEndpoint(propertyPath);
      path = propertyPath;
    }
    suspect.getValueBindingEndpoints().add(endpoint);
    suspect.setLabelI18nKey(path);
    suspect.setLabel(propertyPath);
  }
  
  /**
   * Creates a binding which points to the container of the property
   */
  public void createModelValueContainerBinding(final YSuspect suspect, final String propertyPath, final JvmType type, final String property) {
    String fieldProperty = property;
    boolean _contains = fieldProperty.contains(".");
    if (_contains) {
      fieldProperty = fieldProperty.substring(0, fieldProperty.lastIndexOf("."));
    } else {
      fieldProperty = null;
    }
    final YBeanSlot subTypeBeanSlot = this.findSubTypeBeanSlot(suspect);
    YValueBindingEndpoint endpoint = null;
    if ((subTypeBeanSlot == null)) {
      UiBindingExpression _autoWireSource = this.uiLayout.getAutoWireSource();
      final UiBindingEndpointAssignment uiModelEndpoint = ((UiBindingEndpointAssignment) _autoWireSource);
      final YValueBindingEndpoint yModelEndpoint = this.computer.createValueBindingEndpoint(uiModelEndpoint);
      endpoint = yModelEndpoint;
      if ((fieldProperty != null)) {
        final YDetailValueBindingEndpoint detailValueEndpoint = yModelEndpoint.createDetailValueEndpoint();
        detailValueEndpoint.setPropertyPath(propertyPath);
        detailValueEndpoint.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), 
          this.beanType.getQualifiedName()));
        endpoint = detailValueEndpoint;
      }
    } else {
      endpoint = subTypeBeanSlot.createBindingEndpoint(propertyPath);
    }
    suspect.setContainerValueBindingEndpoint(endpoint);
  }
  
  /**
   * Checks if the suspect is contained in an YSubTypeSuspect. <br>
   * If so, then the detail beanslot of the YSubTypeSuspect is returned. Null otherwise.
   */
  public YBeanSlot findSubTypeBeanSlot(final YSuspect suspect) {
    if ((suspect == null)) {
      return null;
    }
    if ((suspect instanceof YSubTypeSuspect)) {
      return ((YSubTypeSuspect)suspect).getBeanSlot();
    }
    final EObject parent = suspect.eContainer();
    if ((parent instanceof YSuspect)) {
      return this.findSubTypeBeanSlot(((YSuspect)parent));
    }
    return null;
  }
  
  /**
   * Create the bindings and install at the view
   */
  public void createModelListBinding(final YSuspect suspect, final OperationExtensions.OperationInfo info, final JvmType type, final String fieldProperty) {
    final YBeanSlot subTypeBeanSlot = this.findSubTypeBeanSlot(suspect);
    YListBindingEndpoint endpoint = null;
    if ((subTypeBeanSlot == null)) {
      UiBindingExpression _autoWireSource = this.uiLayout.getAutoWireSource();
      final UiBindingEndpointAssignment uiModelEndpoint = ((UiBindingEndpointAssignment) _autoWireSource);
      endpoint = this.createListBindingEndpointWithNested(uiModelEndpoint, info.getName());
    } else {
      endpoint = subTypeBeanSlot.createListBindingEndpoint(info.getName(), subTypeBeanSlot.getValueType());
    }
    suspect.getValueBindingEndpoints().add(endpoint);
    suspect.setLabelI18nKey(info.getName());
    suspect.setLabel(info.getName());
  }
  
  /**
   * Creates a listbinding with respect to nested collection fields. <p>
   * For instance:<br>
   * beanSlot contains Person. We want to bind the children of persons father to a table.
   * So we need to access the children collection of the beanslot by a nested property path: <code>beanslot.father.children</code>
   */
  public YListBindingEndpoint createListBindingEndpointWithNested(final UiBindingEndpointAssignment epDef, final String attributePath) {
    if ((epDef == null)) {
      return null;
    }
    YListBindingEndpoint result = null;
    final BindingInfoHelper.BindingInfo info = new BindingInfoHelper.BindingInfo();
    this.bindingInfoHelper.collectBindingInfo(epDef, info);
    EObject _bindingRoot = info.getBindingRoot();
    if ((_bindingRoot instanceof UiBeanSlot)) {
      EObject _bindingRoot_1 = info.getBindingRoot();
      final UiBeanSlot uiBeanSlot = ((UiBeanSlot) _bindingRoot_1);
      final YBeanSlot yBeanSlot = this.computer.<YBeanSlot>associatedUi(uiBeanSlot);
      final YBeanSlotListBindingEndpoint ep = this.factory.createBeanSlotListBindingEndpoint();
      ep.setBeanSlot(yBeanSlot);
      ep.setAttributePath(this.toNestedCollectionPath(info, attributePath));
      result = ep;
    } else {
      EObject _bindingRoot_2 = info.getBindingRoot();
      if ((_bindingRoot_2 instanceof UiEmbeddable)) {
        final YEmbeddable yElement = this.computer.<YEmbeddable>associatedUi(info.getBindingRoot());
        final YECViewModelListBindingEndpoint ep_1 = this.factory.createECViewModelListBindingEndpoint();
        ep_1.setElement(yElement);
        ep_1.setPropertyPath(this.toNestedCollectionPath(info, attributePath));
        JvmType _typeForBinding = info.getTypeForBinding();
        boolean _tripleNotEquals = (_typeForBinding != null);
        if (_tripleNotEquals) {
          ep_1.setTypeQualifiedName(info.getTypeForBinding().getQualifiedName());
          ep_1.setType(this.computer.loadClass(epDef.eResource().getResourceSet(), ep_1.getTypeQualifiedName()));
        }
        if ((yElement != null)) {
          ep_1.setEmfNsURI(yElement.eClass().getEPackage().getNsURI());
        }
        result = ep_1;
      }
    }
    return result;
  }
  
  public String toNestedCollectionPath(final BindingInfoHelper.BindingInfo info, final String attributePath) {
    String _xblockexpression = null;
    {
      final StringBuilder b = new StringBuilder();
      boolean _isNullOrEmpty = StringExtensions.isNullOrEmpty(info.getPath().toString());
      boolean _not = (!_isNullOrEmpty);
      if (_not) {
        b.append(info.getPath().toString());
      }
      boolean _isNullOrEmpty_1 = StringExtensions.isNullOrEmpty(attributePath);
      boolean _not_1 = (!_isNullOrEmpty_1);
      if (_not_1) {
        int _length = b.length();
        boolean _greaterThan = (_length > 0);
        if (_greaterThan) {
          b.append(".");
        }
        b.append(attributePath);
      }
      final String pathResult = b.toString();
      _xblockexpression = pathResult;
    }
    return _xblockexpression;
  }
  
  /**
   * Creates y column info element
   */
  public YColumnInfo createYColumnInfo(final JvmType type) {
    YColumnInfo _xblockexpression = null;
    {
      final YColumnInfo columnInfo = YECviewFactory.eINSTANCE.createYColumnInfo();
      columnInfo.setTypeQualifiedName(type.getQualifiedName());
      columnInfo.setType(this.computer.loadClass(this.uiLayout.eResource().getResourceSet(), columnInfo.getTypeQualifiedName()));
      _xblockexpression = columnInfo;
    }
    return _xblockexpression;
  }
  
  /**
   * Sets properties into y column info
   */
  public void setYColumnInfoProperties(final YColumnInfo columnInfo, final List<AutowireUtil.Pair> propList) {
    EMap<String, String> properties = columnInfo.getProperties();
    if ((propList != null)) {
      for (final AutowireUtil.Pair prop : propList) {
        properties.put(prop.key, prop.value);
      }
    }
  }
}
