/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), 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:
 *         Florian Pirchner - Initial implementation
 */
package org.eclipse.osbp.dsl.dto.xtext.jvmmodel;

import com.google.common.base.Objects;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import org.eclipse.emf.common.util.EList;
import org.eclipse.osbp.dsl.dto.xtext.extensions.AnnotationExtension;
import org.eclipse.osbp.dsl.dto.xtext.extensions.DtoModelExtensions;
import org.eclipse.osbp.dsl.dto.xtext.jvmmodel.TypeHelper;
import org.eclipse.osbp.dsl.semantic.common.types.LAnnotationDef;
import org.eclipse.osbp.dsl.semantic.common.types.LAnnotationTarget;
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute;
import org.eclipse.osbp.dsl.semantic.common.types.LAttributeMatchingConstraint;
import org.eclipse.osbp.dsl.semantic.common.types.LDataType;
import org.eclipse.osbp.dsl.semantic.common.types.LDatatypeConstraint;
import org.eclipse.osbp.dsl.semantic.common.types.LFeature;
import org.eclipse.osbp.dsl.semantic.common.types.LKeyAndValue;
import org.eclipse.osbp.dsl.semantic.common.types.LOperation;
import org.eclipse.osbp.dsl.semantic.common.types.LReference;
import org.eclipse.osbp.dsl.semantic.common.types.LResultFilter;
import org.eclipse.osbp.dsl.semantic.common.types.LResultFilters;
import org.eclipse.osbp.dsl.semantic.common.types.LScalarType;
import org.eclipse.osbp.dsl.semantic.common.types.LType;
import org.eclipse.osbp.dsl.semantic.dto.LDto;
import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractAttribute;
import org.eclipse.osbp.dsl.semantic.dto.LDtoAttribute;
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedAttribute;
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedReference;
import org.eclipse.osbp.dsl.semantic.dto.LDtoReference;
import org.eclipse.osbp.dsl.semantic.entity.LBean;
import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute;
import org.eclipse.osbp.dsl.semantic.entity.LBeanReference;
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute;
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference;
import org.eclipse.osbp.runtime.common.annotations.AsGrid;
import org.eclipse.osbp.runtime.common.annotations.AsKanbanOrdering;
import org.eclipse.osbp.runtime.common.annotations.AsKanbanState;
import org.eclipse.osbp.runtime.common.annotations.AsTable;
import org.eclipse.osbp.runtime.common.annotations.CreateAt;
import org.eclipse.osbp.runtime.common.annotations.CreateBy;
import org.eclipse.osbp.runtime.common.annotations.Dirty;
import org.eclipse.osbp.runtime.common.annotations.Dispose;
import org.eclipse.osbp.runtime.common.annotations.DomainDescription;
import org.eclipse.osbp.runtime.common.annotations.DomainKey;
import org.eclipse.osbp.runtime.common.annotations.DomainReference;
import org.eclipse.osbp.runtime.common.annotations.ExtraStyle;
import org.eclipse.osbp.runtime.common.annotations.Filter;
import org.eclipse.osbp.runtime.common.annotations.FilterDepth;
import org.eclipse.osbp.runtime.common.annotations.Hidden;
import org.eclipse.osbp.runtime.common.annotations.HistIsCurrent;
import org.eclipse.osbp.runtime.common.annotations.HistIsCustomVersion;
import org.eclipse.osbp.runtime.common.annotations.HistValidUntil;
import org.eclipse.osbp.runtime.common.annotations.HistorizedObject;
import org.eclipse.osbp.runtime.common.annotations.Id;
import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard;
import org.eclipse.osbp.runtime.common.annotations.Range;
import org.eclipse.osbp.runtime.common.annotations.ReadOnly;
import org.eclipse.osbp.runtime.common.annotations.SideKick;
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraint;
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraints;
import org.eclipse.osbp.runtime.common.annotations.TimedependentObject;
import org.eclipse.osbp.runtime.common.annotations.UIGroup;
import org.eclipse.osbp.runtime.common.annotations.UniqueEntry;
import org.eclipse.osbp.runtime.common.annotations.UpdateAt;
import org.eclipse.osbp.runtime.common.annotations.UpdateBy;
import org.eclipse.osbp.runtime.common.annotations.Version;
import org.eclipse.xtext.common.types.JvmAnnotationReference;
import org.eclipse.xtext.common.types.JvmFeature;
import org.eclipse.xtext.common.types.JvmField;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmMember;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.util.TypeReferences;
import org.eclipse.xtext.xbase.annotations.xAnnotations.XAnnotation;
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;

/**
 * This class is responsible to generate the Annotations defined in the entity model
 */
@SuppressWarnings("all")
public class AnnotationCompiler extends org.eclipse.osbp.dsl.common.xtext.jvmmodel.AnnotationCompiler {
  @Inject
  @Extension
  private JvmTypesBuilder _jvmTypesBuilder;
  
  @Inject
  @Extension
  private TypeHelper _typeHelper;
  
  @Inject
  @Extension
  private DtoModelExtensions _dtoModelExtensions;
  
  @Inject
  @Extension
  private AnnotationExtension _annotationExtension;
  
  @Inject
  private TypeReferences references;
  
  protected void _internalProcessAnnotation(final LDto dto, final JvmGenericType jvmType) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(dto.getResolvedAnnotations(), _function), _function_1), jvmType);
    boolean _isHistorized = dto.isHistorized();
    if (_isHistorized) {
      this._annotationExtension.addAnno(dto, jvmType, this._jvmTypesBuilder.toAnnotation(dto, HistorizedObject.class));
    } else {
      boolean _isTimedependent = dto.isTimedependent();
      if (_isTimedependent) {
        this._annotationExtension.addAnno(dto, jvmType, this._jvmTypesBuilder.toAnnotation(dto, TimedependentObject.class));
      }
    }
  }
  
  protected void _internalProcessAnnotation(final LDtoReference prop, final JvmGenericType jvmType) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(prop.getResolvedAnnotations(), _function), _function_1), jvmType);
  }
  
  protected void _internalProcessAnnotation(final LDtoReference prop, final JvmField field) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(prop.getResolvedAnnotations(), _function), _function_1), field);
    EList<JvmAnnotationReference> _annotations = field.getAnnotations();
    JvmAnnotationReference _annotation = this._jvmTypesBuilder.toAnnotation(prop, DomainReference.class);
    this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations, _annotation);
    boolean _isCascading = prop.isCascading();
    if (_isCascading) {
      this.toValidAnnotation(prop, field);
    }
    this.toPropertiesAnnotation(prop, this.mergeKeyAndValues(prop), field);
  }
  
  protected List<LKeyAndValue> mergeKeyAndValues(final LDtoInheritedAttribute att) {
    final ArrayList<LKeyAndValue> keyAndValues = CollectionLiterals.<LKeyAndValue>newArrayList();
    this.addDatatypeKeyAndValues(att.getInheritedFeature(), keyAndValues);
    keyAndValues.addAll(att.getInheritedFeature().getProperties());
    keyAndValues.addAll(att.getProperties());
    this.removeDuplicateKeys(keyAndValues);
    return keyAndValues;
  }
  
  protected List<LKeyAndValue> mergeKeyAndValues(final LDtoInheritedReference ref) {
    final ArrayList<LKeyAndValue> keyAndValues = CollectionLiterals.<LKeyAndValue>newArrayList();
    keyAndValues.addAll(ref.getInheritedFeature().getProperties());
    keyAndValues.addAll(ref.getProperties());
    this.removeDuplicateKeys(keyAndValues);
    return keyAndValues;
  }
  
  protected void _internalProcessAnnotation(final LDtoAttribute prop, final JvmField field) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(prop.getResolvedAnnotations(), _function), _function_1), field);
    if ((prop.isId() || prop.isUuid())) {
      EList<JvmAnnotationReference> _annotations = field.getAnnotations();
      JvmAnnotationReference _annotation = this._jvmTypesBuilder.toAnnotation(prop, Id.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations, _annotation);
    }
    boolean _isVersion = prop.isVersion();
    if (_isVersion) {
      EList<JvmAnnotationReference> _annotations_1 = field.getAnnotations();
      JvmAnnotationReference _annotation_1 = this._jvmTypesBuilder.toAnnotation(prop, Version.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_1, _annotation_1);
    }
    boolean _isDomainKey = prop.isDomainKey();
    if (_isDomainKey) {
      EList<JvmAnnotationReference> _annotations_2 = field.getAnnotations();
      JvmAnnotationReference _annotation_2 = this._jvmTypesBuilder.toAnnotation(prop, DomainKey.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_2, _annotation_2);
    }
    boolean _isDomainDescription = prop.isDomainDescription();
    if (_isDomainDescription) {
      EList<JvmAnnotationReference> _annotations_3 = field.getAnnotations();
      JvmAnnotationReference _annotation_3 = this._jvmTypesBuilder.toAnnotation(prop, DomainDescription.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_3, _annotation_3);
    }
    boolean _isDirty = prop.isDirty();
    if (_isDirty) {
      EList<JvmAnnotationReference> _annotations_4 = field.getAnnotations();
      JvmAnnotationReference _annotation_4 = this._jvmTypesBuilder.toAnnotation(prop, Dirty.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_4, _annotation_4);
    }
    boolean _isAttributeHidden = prop.isAttributeHidden();
    if (_isAttributeHidden) {
      EList<JvmAnnotationReference> _annotations_5 = field.getAnnotations();
      JvmAnnotationReference _annotation_5 = this._jvmTypesBuilder.toAnnotation(prop, Hidden.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_5, _annotation_5);
    }
    boolean _isAttributeReadOnly = prop.isAttributeReadOnly();
    if (_isAttributeReadOnly) {
      EList<JvmAnnotationReference> _annotations_6 = field.getAnnotations();
      JvmAnnotationReference _annotation_6 = this._jvmTypesBuilder.toAnnotation(prop, ReadOnly.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_6, _annotation_6);
    }
    String _extraStyle = prop.getExtraStyle();
    boolean _tripleNotEquals = (_extraStyle != null);
    if (_tripleNotEquals) {
      final JvmAnnotationReference styleAnnotation = this._jvmTypesBuilder.toAnnotation(prop, ExtraStyle.class);
      this._annotationExtension.addAnnAttr(styleAnnotation, prop, "name", prop.getExtraStyle());
      EList<JvmAnnotationReference> _annotations_7 = field.getAnnotations();
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_7, styleAnnotation);
    }
    this.toPropertiesAnnotation(prop, this.mergeKeyAndValues(prop), field);
    boolean _isValidAllowed = this.isValidAllowed(prop.getType());
    if (_isValidAllowed) {
      this.toValidAnnotation(prop, field);
    }
    super.toDatatypeBasedConstraintAnnotations(prop, field);
  }
  
  protected void _internalProcessAnnotation(final LDtoInheritedAttribute prop, final JvmField field) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(prop.getResolvedAnnotations(), _function), _function_1), field);
    if ((prop.getInheritedFeature().isId() || prop.getInheritedFeature().isUuid())) {
      EList<JvmAnnotationReference> _annotations = field.getAnnotations();
      JvmAnnotationReference _annotation = this._jvmTypesBuilder.toAnnotation(prop, Id.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations, _annotation);
    }
    boolean _isVersion = prop.getInheritedFeature().isVersion();
    if (_isVersion) {
      EList<JvmAnnotationReference> _annotations_1 = field.getAnnotations();
      JvmAnnotationReference _annotation_1 = this._jvmTypesBuilder.toAnnotation(prop, Version.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_1, _annotation_1);
    }
    boolean _isDomainKey = prop.getInheritedFeature().isDomainKey();
    if (_isDomainKey) {
      EList<JvmAnnotationReference> _annotations_2 = field.getAnnotations();
      JvmAnnotationReference _annotation_2 = this._jvmTypesBuilder.toAnnotation(prop, DomainKey.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_2, _annotation_2);
    }
    boolean _isDomainDescription = prop.getInheritedFeature().isDomainDescription();
    if (_isDomainDescription) {
      EList<JvmAnnotationReference> _annotations_3 = field.getAnnotations();
      JvmAnnotationReference _annotation_3 = this._jvmTypesBuilder.toAnnotation(prop, DomainDescription.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_3, _annotation_3);
    }
    boolean _isAttributeHidden = prop.getInheritedFeature().isAttributeHidden();
    if (_isAttributeHidden) {
      EList<JvmAnnotationReference> _annotations_4 = field.getAnnotations();
      JvmAnnotationReference _annotation_4 = this._jvmTypesBuilder.toAnnotation(prop, Hidden.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_4, _annotation_4);
    }
    boolean _isAttributeReadOnly = prop.getInheritedFeature().isAttributeReadOnly();
    if (_isAttributeReadOnly) {
      EList<JvmAnnotationReference> _annotations_5 = field.getAnnotations();
      JvmAnnotationReference _annotation_5 = this._jvmTypesBuilder.toAnnotation(prop, ReadOnly.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_5, _annotation_5);
    }
    String _extraStyle = prop.getInheritedFeature().getExtraStyle();
    boolean _tripleNotEquals = (_extraStyle != null);
    if (_tripleNotEquals) {
      final JvmAnnotationReference styleAnnotation = this._jvmTypesBuilder.toAnnotation(prop, ExtraStyle.class);
      this._annotationExtension.addAnnAttr(styleAnnotation, prop, "name", prop.getInheritedFeature().getExtraStyle());
      EList<JvmAnnotationReference> _annotations_6 = field.getAnnotations();
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_6, styleAnnotation);
    }
    this.toPropertiesAnnotation(prop, this.mergeKeyAndValues(prop), field);
    boolean _isValidAllowed = this.isValidAllowed(prop.getInheritedFeature().getType());
    if (_isValidAllowed) {
      this.toValidAnnotation(prop, field);
    }
    if (((prop.getInheritedFeature().getType() instanceof LBean) && ((LBean) prop.getInheritedFeature().getType()).isBeanOnTab())) {
      this.toBeanOnTabAnnotation(prop, field);
    }
    boolean _isFiltering = prop.getInheritedFeature().isFiltering();
    if (_isFiltering) {
      EList<JvmAnnotationReference> _annotations_7 = field.getAnnotations();
      JvmAnnotationReference _annotation_6 = this._jvmTypesBuilder.toAnnotation(prop, Filter.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_7, _annotation_6);
    }
    boolean _isRangeFiltering = prop.getInheritedFeature().isRangeFiltering();
    if (_isRangeFiltering) {
      EList<JvmAnnotationReference> _annotations_8 = field.getAnnotations();
      JvmAnnotationReference _annotation_7 = this._jvmTypesBuilder.toAnnotation(prop, Range.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_8, _annotation_7);
    }
    boolean _isUniqueEntry = prop.getInheritedFeature().isUniqueEntry();
    if (_isUniqueEntry) {
      EList<JvmAnnotationReference> _annotations_9 = field.getAnnotations();
      JvmAnnotationReference _annotation_8 = this._jvmTypesBuilder.toAnnotation(prop, UniqueEntry.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_9, _annotation_8);
    }
    LAttribute _inheritedFeature = prop.getInheritedFeature();
    if ((_inheritedFeature instanceof LEntityAttribute)) {
      LAttribute _inheritedFeature_1 = prop.getInheritedFeature();
      final LEntityAttribute att = ((LEntityAttribute) _inheritedFeature_1);
      if ((att.getEntity().isHistorized() || att.getEntity().isTimedependent())) {
        boolean _isHistorizedValidUntilAnnotation = this._annotationExtension.isHistorizedValidUntilAnnotation(att);
        if (_isHistorizedValidUntilAnnotation) {
          EList<JvmAnnotationReference> _annotations_10 = field.getAnnotations();
          JvmAnnotationReference _annotation_9 = this._jvmTypesBuilder.toAnnotation(prop, HistValidUntil.class);
          this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_10, _annotation_9);
        }
        boolean _isHistorizedIsCurrentAnnotation = this._annotationExtension.isHistorizedIsCurrentAnnotation(att);
        if (_isHistorizedIsCurrentAnnotation) {
          EList<JvmAnnotationReference> _annotations_11 = field.getAnnotations();
          JvmAnnotationReference _annotation_10 = this._jvmTypesBuilder.toAnnotation(prop, HistIsCurrent.class);
          this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_11, _annotation_10);
        }
        boolean _isHistorizedIsCustomVersionAnnotation = this._annotationExtension.isHistorizedIsCustomVersionAnnotation(att);
        if (_isHistorizedIsCustomVersionAnnotation) {
          EList<JvmAnnotationReference> _annotations_12 = field.getAnnotations();
          JvmAnnotationReference _annotation_11 = this._jvmTypesBuilder.toAnnotation(prop, HistIsCustomVersion.class);
          this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_12, _annotation_11);
        }
      }
      boolean _isOnKanbanCard = att.isOnKanbanCard();
      if (_isOnKanbanCard) {
        EList<JvmAnnotationReference> _annotations_13 = field.getAnnotations();
        JvmAnnotationReference _annotation_12 = this._jvmTypesBuilder.toAnnotation(prop, OnKanbanCard.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_13, _annotation_12);
      }
      boolean _isAsKanbanOrdering = att.isAsKanbanOrdering();
      if (_isAsKanbanOrdering) {
        EList<JvmAnnotationReference> _annotations_14 = field.getAnnotations();
        JvmAnnotationReference _annotation_13 = this._jvmTypesBuilder.toAnnotation(prop, AsKanbanOrdering.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_14, _annotation_13);
      }
      boolean _isAsKanbanState = att.isAsKanbanState();
      if (_isAsKanbanState) {
        EList<JvmAnnotationReference> _annotations_15 = field.getAnnotations();
        JvmAnnotationReference _annotation_14 = this._jvmTypesBuilder.toAnnotation(prop, AsKanbanState.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_15, _annotation_14);
      }
      boolean _annotationPresent = this.annotationPresent(att, this.references.findDeclaredType(UpdateBy.class, att));
      if (_annotationPresent) {
        EList<JvmAnnotationReference> _annotations_16 = field.getAnnotations();
        JvmAnnotationReference _annotation_15 = this._jvmTypesBuilder.toAnnotation(prop, UpdateBy.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_16, _annotation_15);
      }
      boolean _annotationPresent_1 = this.annotationPresent(att, this.references.findDeclaredType(UpdateAt.class, att));
      if (_annotationPresent_1) {
        EList<JvmAnnotationReference> _annotations_17 = field.getAnnotations();
        JvmAnnotationReference _annotation_16 = this._jvmTypesBuilder.toAnnotation(prop, UpdateAt.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_17, _annotation_16);
      }
      boolean _annotationPresent_2 = this.annotationPresent(att, this.references.findDeclaredType(CreateBy.class, att));
      if (_annotationPresent_2) {
        EList<JvmAnnotationReference> _annotations_18 = field.getAnnotations();
        JvmAnnotationReference _annotation_17 = this._jvmTypesBuilder.toAnnotation(prop, CreateBy.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_18, _annotation_17);
      }
      boolean _annotationPresent_3 = this.annotationPresent(att, this.references.findDeclaredType(CreateAt.class, att));
      if (_annotationPresent_3) {
        EList<JvmAnnotationReference> _annotations_19 = field.getAnnotations();
        JvmAnnotationReference _annotation_18 = this._jvmTypesBuilder.toAnnotation(prop, CreateAt.class);
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_19, _annotation_18);
      }
      boolean _isIsGrouped = att.isIsGrouped();
      if (_isIsGrouped) {
        final JvmAnnotationReference groupAnnotation = this._jvmTypesBuilder.toAnnotation(prop, UIGroup.class);
        this._annotationExtension.addAnnAttr(groupAnnotation, prop, "name", att.getGroupName());
        EList<JvmAnnotationReference> _annotations_20 = field.getAnnotations();
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_20, groupAnnotation);
      }
    }
    this.toInheritedConstraintAnnotations(prop.getInheritedFeature(), field);
  }
  
  public boolean annotationPresent(final LEntityAttribute attribute, final JvmType type) {
    EList<LAnnotationDef> _resolvedAnnotations = attribute.getResolvedAnnotations();
    for (final LAnnotationDef anno : _resolvedAnnotations) {
      JvmType _annotationType = anno.getAnnotation().getAnnotationType();
      boolean _tripleEquals = (_annotationType == type);
      if (_tripleEquals) {
        return true;
      }
    }
    return false;
  }
  
  protected void _internalProcessAnnotation(final LDtoInheritedReference prop, final JvmField field) {
    final Function1<LAnnotationDef, Boolean> _function = (LAnnotationDef it) -> {
      boolean _isExclude = it.isExclude();
      return Boolean.valueOf((!_isExclude));
    };
    final Function1<LAnnotationDef, XAnnotation> _function_1 = (LAnnotationDef it) -> {
      return it.getAnnotation();
    };
    this._jvmTypesBuilder.translateAnnotationsTo(IterableExtensions.<LAnnotationDef, XAnnotation>map(IterableExtensions.<LAnnotationDef>filter(prop.getResolvedAnnotations(), _function), _function_1), field);
    EList<JvmAnnotationReference> _annotations = field.getAnnotations();
    JvmAnnotationReference _annotation = this._jvmTypesBuilder.toAnnotation(prop, DomainReference.class);
    this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations, _annotation);
    final LReference inheritedRef = prop.getInheritedFeature();
    if ((inheritedRef instanceof LEntityReference)) {
      LResultFilters _resultFilters = ((LEntityReference)inheritedRef).getResultFilters();
      boolean _notEquals = (!Objects.equal(_resultFilters, null));
      if (_notEquals) {
        this.addConstraintsAnno(((LEntityReference)inheritedRef).getResultFilters(), field, prop.getType());
      }
      boolean _isCascading = ((LEntityReference)inheritedRef).isCascading();
      if (_isCascading) {
        this.toValidAnnotation(prop, field);
      }
      this.toInheritedConstraintAnnotations(inheritedRef, field);
      this.toPropertiesAnnotation(prop, this.mergeKeyAndValues(prop), field);
      int _filterDepth = ((LEntityReference)inheritedRef).getFilterDepth();
      boolean _greaterEqualsThan = (_filterDepth >= 0);
      if (_greaterEqualsThan) {
        final JvmAnnotationReference anno = this._jvmTypesBuilder.toAnnotation(inheritedRef, FilterDepth.class);
        this._annotationExtension.addAnnAttr(anno, inheritedRef, "depth", Integer.valueOf(((LEntityReference)inheritedRef).getFilterDepth()));
        EList<JvmAnnotationReference> _annotations_1 = field.getAnnotations();
        this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_1, anno);
      }
    } else {
      if ((inheritedRef instanceof LBeanReference)) {
        LResultFilters _resultFilters_1 = ((LBeanReference)inheritedRef).getResultFilters();
        boolean _notEquals_1 = (!Objects.equal(_resultFilters_1, null));
        if (_notEquals_1) {
          this.addConstraintsAnno(((LBeanReference)inheritedRef).getResultFilters(), field, prop.getType());
        }
        boolean _isCascading_1 = ((LBeanReference)inheritedRef).isCascading();
        if (_isCascading_1) {
          this.toValidAnnotation(prop, field);
        }
        this.toInheritedConstraintAnnotations(inheritedRef, field);
        this.toPropertiesAnnotation(prop, this.mergeKeyAndValues(prop), field);
      }
    }
    boolean _isIsGrouped = inheritedRef.isIsGrouped();
    if (_isIsGrouped) {
      final JvmAnnotationReference groupAnnotation = this._jvmTypesBuilder.toAnnotation(prop, UIGroup.class);
      this._annotationExtension.addAnnAttr(groupAnnotation, prop, "name", inheritedRef.getGroupName());
      EList<JvmAnnotationReference> _annotations_2 = field.getAnnotations();
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_2, groupAnnotation);
    }
    boolean _isAsGrid = inheritedRef.isAsGrid();
    if (_isAsGrid) {
      EList<JvmAnnotationReference> _annotations_3 = field.getAnnotations();
      JvmAnnotationReference _annotation_1 = this._jvmTypesBuilder.toAnnotation(prop, AsGrid.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_3, _annotation_1);
    }
    boolean _isAsTable = inheritedRef.isAsTable();
    if (_isAsTable) {
      EList<JvmAnnotationReference> _annotations_4 = field.getAnnotations();
      JvmAnnotationReference _annotation_2 = this._jvmTypesBuilder.toAnnotation(prop, AsTable.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_4, _annotation_2);
    }
    boolean _isSideKick = inheritedRef.isSideKick();
    if (_isSideKick) {
      EList<JvmAnnotationReference> _annotations_5 = field.getAnnotations();
      JvmAnnotationReference _annotation_3 = this._jvmTypesBuilder.toAnnotation(prop, SideKick.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_5, _annotation_3);
    }
    boolean _isReferenceHidden = inheritedRef.isReferenceHidden();
    if (_isReferenceHidden) {
      EList<JvmAnnotationReference> _annotations_6 = field.getAnnotations();
      JvmAnnotationReference _annotation_4 = this._jvmTypesBuilder.toAnnotation(prop, Hidden.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_6, _annotation_4);
    }
    boolean _isReferenceReadOnly = inheritedRef.isReferenceReadOnly();
    if (_isReferenceReadOnly) {
      EList<JvmAnnotationReference> _annotations_7 = field.getAnnotations();
      JvmAnnotationReference _annotation_5 = this._jvmTypesBuilder.toAnnotation(prop, ReadOnly.class);
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations_7, _annotation_5);
    }
  }
  
  public void addConstraintsAnno(final LResultFilters constraints, final JvmField jvmField, final LDto mapsTo) {
    final Function1<LResultFilter, Boolean> _function = (LResultFilter it) -> {
      return Boolean.valueOf((it instanceof LAttributeMatchingConstraint));
    };
    boolean _isEmpty = IterableExtensions.isEmpty(IterableExtensions.<LResultFilter>filter(constraints.getResultFilters(), _function));
    boolean _not = (!_isEmpty);
    if (_not) {
      final ArrayList<JvmAnnotationReference> innerAnnotations = CollectionLiterals.<JvmAnnotationReference>newArrayList();
      final Function1<LResultFilter, Boolean> _function_1 = (LResultFilter it) -> {
        return Boolean.valueOf((it instanceof LAttributeMatchingConstraint));
      };
      final Function1<LResultFilter, LAttributeMatchingConstraint> _function_2 = (LResultFilter it) -> {
        return ((LAttributeMatchingConstraint) it);
      };
      final Consumer<LAttributeMatchingConstraint> _function_3 = (LAttributeMatchingConstraint it) -> {
        final JvmTypeReference enumClassTypeRef = this.findReplacementEnum(it.getAttribute().getName(), mapsTo);
        boolean _notEquals = (!Objects.equal(enumClassTypeRef, null));
        if (_notEquals) {
          final JvmAnnotationReference innerAnno = this._jvmTypesBuilder.toAnnotation(constraints, TargetEnumConstraint.class);
          this._annotationExtension.addAnnAttr(innerAnno, it, "targetProperty", it.getAttribute().getName());
          this._annotationExtension.addAnnAttr(innerAnno, it, "enumClass", enumClassTypeRef);
          this._annotationExtension.addAnnAttr(innerAnno, it, "enumLiteral", it.getMatchingLiteral().getName());
          innerAnnotations.add(innerAnno);
        }
      };
      IterableExtensions.<LResultFilter, LAttributeMatchingConstraint>map(IterableExtensions.<LResultFilter>filter(constraints.getResultFilters(), _function_1), _function_2).forEach(_function_3);
      final JvmAnnotationReference mainAnno = this._jvmTypesBuilder.toAnnotation(constraints, TargetEnumConstraints.class);
      this._annotationExtension.addAnnAttr(mainAnno, constraints, "constraints", 
        innerAnnotations.<JvmAnnotationReference>toArray(new JvmAnnotationReference[((Object[])Conversions.unwrapArray(innerAnnotations, Object.class)).length]));
      EList<JvmAnnotationReference> _annotations = jvmField.getAnnotations();
      this._jvmTypesBuilder.<JvmAnnotationReference>operator_add(_annotations, mainAnno);
    }
  }
  
  /**
   * Iterates all attributes of the target dto. If a matching att name was found, the jvmType proxy will be returned.
   */
  public JvmTypeReference findReplacementEnum(final String property, final LDto mapsTo) {
    final Function1<LFeature, Boolean> _function = (LFeature it) -> {
      return Boolean.valueOf((it instanceof LDtoAbstractAttribute));
    };
    final Function1<LFeature, LDtoAbstractAttribute> _function_1 = (LFeature it) -> {
      return ((LDtoAbstractAttribute) it);
    };
    Iterable<LDtoAbstractAttribute> _map = IterableExtensions.map(IterableExtensions.filter(mapsTo.getAllFeatures(), _function), _function_1);
    for (final LDtoAbstractAttribute att : _map) {
      if ((att instanceof LDtoInheritedAttribute)) {
        LAttribute _inheritedFeature = ((LDtoInheritedAttribute)att).getInheritedFeature();
        String _name = null;
        if (_inheritedFeature!=null) {
          _name=_inheritedFeature.getName();
        }
        boolean _equals = _name.equals(property);
        if (_equals) {
          return this._dtoModelExtensions.toDtoTypeReference(att);
        }
      } else {
        boolean _equals_1 = att.getName().equals(property);
        if (_equals_1) {
          return this._dtoModelExtensions.toDtoTypeReference(att);
        }
      }
    }
    return null;
  }
  
  protected boolean _addDisposeFieldAnnotation(final LDto dto, final JvmField field) {
    return this._annotationExtension.addAnno(dto, field, this._jvmTypesBuilder.toAnnotation(dto, Dispose.class));
  }
  
  protected boolean _addDisposeFieldAnnotation(final LDto dto, final JvmOperation op) {
    return this._annotationExtension.addAnno(dto, op, this._jvmTypesBuilder.toAnnotation(dto, Dispose.class));
  }
  
  protected boolean _isValidAllowed(final LBean type) {
    return true;
  }
  
  protected void _toInheritedConstraintAnnotations(final LDtoInheritedAttribute prop, final JvmField jvmField) {
    final LAttribute feature = prop.getInheritedFeature();
    if ((feature instanceof LBeanAttribute)) {
      this.toInheritedConstraintAnnotations(feature, jvmField);
    } else {
      if ((feature instanceof LEntityAttribute)) {
        this.toInheritedConstraintAnnotations(feature, jvmField);
      }
    }
  }
  
  protected void _toInheritedConstraintAnnotations(final LBeanAttribute prop, final JvmField jvmField) {
    EList<LDatatypeConstraint> _constraints = prop.getConstraints();
    for (final LDatatypeConstraint c : _constraints) {
      this.toConstraintAnnotation(c, jvmField);
    }
    boolean _isEmpty = prop.getConstraints().isEmpty();
    if (_isEmpty) {
      super.toDatatypeBasedConstraintAnnotations(prop, jvmField);
    }
  }
  
  protected void _toInheritedConstraintAnnotations(final LBeanReference prop, final JvmField jvmField) {
    EList<LDatatypeConstraint> _constraints = prop.getConstraints();
    for (final LDatatypeConstraint c : _constraints) {
      this.toConstraintAnnotation(c, jvmField);
    }
  }
  
  protected void _toInheritedConstraintAnnotations(final LEntityAttribute prop, final JvmField jvmField) {
    EList<LDatatypeConstraint> _constraints = prop.getConstraints();
    for (final LDatatypeConstraint c : _constraints) {
      this.toConstraintAnnotation(c, jvmField);
    }
    boolean _isEmpty = prop.getConstraints().isEmpty();
    if (_isEmpty) {
      super.toDatatypeBasedConstraintAnnotations(prop, jvmField);
    }
  }
  
  protected void _toInheritedConstraintAnnotations(final LEntityReference prop, final JvmField jvmField) {
    EList<LDatatypeConstraint> _constraints = prop.getConstraints();
    for (final LDatatypeConstraint c : _constraints) {
      this.toConstraintAnnotation(c, jvmField);
    }
  }
  
  protected void internalProcessAnnotation(final LAnnotationTarget prop, final JvmMember field) {
    if (prop instanceof LDtoAttribute
         && field instanceof JvmField) {
      _internalProcessAnnotation((LDtoAttribute)prop, (JvmField)field);
      return;
    } else if (prop instanceof LDtoInheritedAttribute
         && field instanceof JvmField) {
      _internalProcessAnnotation((LDtoInheritedAttribute)prop, (JvmField)field);
      return;
    } else if (prop instanceof LDtoInheritedReference
         && field instanceof JvmField) {
      _internalProcessAnnotation((LDtoInheritedReference)prop, (JvmField)field);
      return;
    } else if (prop instanceof LDtoReference
         && field instanceof JvmField) {
      _internalProcessAnnotation((LDtoReference)prop, (JvmField)field);
      return;
    } else if (prop instanceof LDtoReference
         && field instanceof JvmGenericType) {
      _internalProcessAnnotation((LDtoReference)prop, (JvmGenericType)field);
      return;
    } else if (prop instanceof LDto
         && field instanceof JvmGenericType) {
      _internalProcessAnnotation((LDto)prop, (JvmGenericType)field);
      return;
    } else if (prop instanceof LAttribute
         && field instanceof JvmField) {
      _internalProcessAnnotation((LAttribute)prop, (JvmField)field);
      return;
    } else if (prop instanceof LReference
         && field instanceof JvmField) {
      _internalProcessAnnotation((LReference)prop, (JvmField)field);
      return;
    } else if (prop instanceof LOperation
         && field instanceof JvmOperation) {
      _internalProcessAnnotation((LOperation)prop, (JvmOperation)field);
      return;
    } else if (prop instanceof LType
         && field instanceof JvmGenericType) {
      _internalProcessAnnotation((LType)prop, (JvmGenericType)field);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(prop, field).toString());
    }
  }
  
  public boolean addDisposeFieldAnnotation(final LDto dto, final JvmFeature op) {
    if (op instanceof JvmOperation) {
      return _addDisposeFieldAnnotation(dto, (JvmOperation)op);
    } else if (op instanceof JvmField) {
      return _addDisposeFieldAnnotation(dto, (JvmField)op);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(dto, op).toString());
    }
  }
  
  public boolean isValidAllowed(final LScalarType type) {
    if (type instanceof LDataType) {
      return _isValidAllowed((LDataType)type);
    } else if (type instanceof LBean) {
      return _isValidAllowed((LBean)type);
    } else if (type != null) {
      return _isValidAllowed(type);
    } else if (type == null) {
      return _isValidAllowed((Void)null);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type).toString());
    }
  }
  
  public void toInheritedConstraintAnnotations(final LFeature prop, final JvmField jvmField) {
    if (prop instanceof LDtoInheritedAttribute) {
      _toInheritedConstraintAnnotations((LDtoInheritedAttribute)prop, jvmField);
      return;
    } else if (prop instanceof LBeanAttribute) {
      _toInheritedConstraintAnnotations((LBeanAttribute)prop, jvmField);
      return;
    } else if (prop instanceof LBeanReference) {
      _toInheritedConstraintAnnotations((LBeanReference)prop, jvmField);
      return;
    } else if (prop instanceof LEntityAttribute) {
      _toInheritedConstraintAnnotations((LEntityAttribute)prop, jvmField);
      return;
    } else if (prop instanceof LEntityReference) {
      _toInheritedConstraintAnnotations((LEntityReference)prop, jvmField);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(prop, jvmField).toString());
    }
  }
}
