All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.contextmapper.tactic.dsl.validation.TacticDDDLanguageValidator Maven / Gradle / Ivy

/**
 * Copyright 2013 The Sculptor Project Team, including the original
 * author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.contextmapper.tactic.dsl.validation;

import com.google.common.base.Objects;
import java.util.Arrays;
import java.util.HashSet;
import java.util.regex.Pattern;
import org.contextmapper.tactic.dsl.TacticDslExtensions;
import org.contextmapper.tactic.dsl.tacticdsl.AnyProperty;
import org.contextmapper.tactic.dsl.tacticdsl.Attribute;
import org.contextmapper.tactic.dsl.tacticdsl.BasicType;
import org.contextmapper.tactic.dsl.tacticdsl.CollectionType;
import org.contextmapper.tactic.dsl.tacticdsl.DomainObject;
import org.contextmapper.tactic.dsl.tacticdsl.DtoAttribute;
import org.contextmapper.tactic.dsl.tacticdsl.DtoReference;
import org.contextmapper.tactic.dsl.tacticdsl.Entity;
import org.contextmapper.tactic.dsl.tacticdsl.EnumAttribute;
import org.contextmapper.tactic.dsl.tacticdsl.EnumValue;
import org.contextmapper.tactic.dsl.tacticdsl.Event;
import org.contextmapper.tactic.dsl.tacticdsl.Parameter;
import org.contextmapper.tactic.dsl.tacticdsl.Property;
import org.contextmapper.tactic.dsl.tacticdsl.Reference;
import org.contextmapper.tactic.dsl.tacticdsl.Repository;
import org.contextmapper.tactic.dsl.tacticdsl.RepositoryOperation;
import org.contextmapper.tactic.dsl.tacticdsl.Service;
import org.contextmapper.tactic.dsl.tacticdsl.ServiceOperation;
import org.contextmapper.tactic.dsl.tacticdsl.SimpleDomainObject;
import org.contextmapper.tactic.dsl.tacticdsl.TacticdslPackage;
import org.contextmapper.tactic.dsl.tacticdsl.ValueObject;
import org.contextmapper.tactic.dsl.validation.AbstractTacticDDDLanguageValidator;
import org.contextmapper.tactic.dsl.validation.IssueCodes;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.validation.Check;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.IteratorExtensions;

/**
 * Custom validation rules.
 * 
 * see http://www.eclipse.org/Xtext/documentation.html#validation
 */
@SuppressWarnings("all")
public class TacticDDDLanguageValidator extends AbstractTacticDDDLanguageValidator implements IssueCodes {
  private final Pattern DIGITS_PATTERN = Pattern.compile("[0-9]+[0-9]*");
  
  private final HashSet SUPPORTED_PRIMITIVE_TYPES = new HashSet(Arrays.asList("int", "long", "float", "double", "boolean"));
  
  private final HashSet SUPPORTED_TEMPORAL_TYPES = new HashSet(Arrays.asList("Date", "DateTime", "Timestamp"));
  
  private final HashSet SUPPORTED_NUMERIC_TYPES = new HashSet(
    Arrays.asList("int", "long", "float", "double", "Integer", "Long", "Float", "Double", "BigInteger", "BigDecimal"));
  
  private final HashSet SUPPORTED_BOOLEAN_TYPES = new HashSet(Arrays.asList("Boolean", "boolean"));
  
  @Check
  public void checkServiceNameStartsWithUpperCase(final Service service) {
    String _name = service.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isUpperCase = Character.isUpperCase(service.getName().charAt(0));
    boolean _not = (!_isUpperCase);
    if (_not) {
      this.warning("The service name should begin with an upper case letter", TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NAME, 
        IssueCodes.CAPITALIZED_NAME, service.getName());
    }
  }
  
  @Check
  public void checkRepositoryNameStartsWithUpperCase(final Repository repository) {
    String _name = repository.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isUpperCase = Character.isUpperCase(repository.getName().charAt(0));
    boolean _not = (!_isUpperCase);
    if (_not) {
      this.warning("The repository name should begin with an upper case letter", TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NAME, 
        IssueCodes.CAPITALIZED_NAME, repository.getName());
    }
  }
  
  @Check
  public void checkDomainObjectNameStartsWithUpperCase(final SimpleDomainObject domainObject) {
    String _name = domainObject.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isUpperCase = Character.isUpperCase(domainObject.getName().charAt(0));
    boolean _not = (!_isUpperCase);
    if (_not) {
      this.warning("The domain object name should begin with an upper case letter", TacticdslPackage.Literals.SIMPLE_DOMAIN_OBJECT__NAME, 
        IssueCodes.CAPITALIZED_NAME, domainObject.getName());
    }
  }
  
  @Check
  public void checkPropertyNameStartsWithLowerCase(final AnyProperty prop) {
    String _name = prop.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isLowerCase = Character.isLowerCase(prop.getName().charAt(0));
    boolean _not = (!_isLowerCase);
    if (_not) {
      this.warning("Attribute/reference should begin with a lower case letter", TacticdslPackage.Literals.ANY_PROPERTY__NAME, 
        IssueCodes.UNCAPITALIZED_NAME, prop.getName());
    }
  }
  
  @Check
  public void checkParamterNameStartsWithLowerCase(final Parameter param) {
    String _name = param.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isLowerCase = Character.isLowerCase(param.getName().charAt(0));
    boolean _not = (!_isLowerCase);
    if (_not) {
      this.warning("Parameter should begin with a lower case letter", TacticdslPackage.Literals.PARAMETER__NAME, IssueCodes.UNCAPITALIZED_NAME, 
        param.getName());
    }
  }
  
  @Check
  public void checkRequired(final Property prop) {
    if ((prop.isNotChangeable() && prop.isRequired())) {
      this.warning("The combination not changeable and required doesn\'t make sense, remove required", 
        TacticdslPackage.Literals.ANY_PROPERTY__REQUIRED);
    }
  }
  
  @Check
  public void checkKeyNotChangeable(final Property prop) {
    if ((prop.isKey() && prop.isNotChangeable())) {
      this.warning("Key property is always not changeable", TacticdslPackage.Literals.ANY_PROPERTY__NOT_CHANGEABLE);
    }
  }
  
  @Check
  public void checkKeyRequired(final Property prop) {
    if ((prop.isKey() && prop.isRequired())) {
      this.warning("Key property is always required", TacticdslPackage.Literals.ANY_PROPERTY__REQUIRED);
    }
  }
  
  @Check
  public void checkCollectionCache(final Reference ref) {
    if ((ref.isCache() && Objects.equal(ref.getCollectionType(), CollectionType.NONE))) {
      this.error("Cache is only applicable for collections", TacticdslPackage.Literals.REFERENCE__CACHE);
    }
  }
  
  @Check
  public void checkInverse(final Reference ref) {
    boolean _isInverse = ref.isInverse();
    boolean _not = (!_isInverse);
    if (_not) {
      return;
    }
    boolean _not_1 = (!((!Objects.equal(ref.getCollectionType(), CollectionType.NONE)) || (((ref.getOppositeHolder() != null) && (ref.getOppositeHolder().getOpposite() != null)) && Objects.equal(ref.getOppositeHolder().getOpposite().getCollectionType(), CollectionType.NONE))));
    if (_not_1) {
      this.error("Inverse is only applicable for references with cardinality many, or one-to-one", 
        TacticdslPackage.Literals.REFERENCE__INVERSE);
    }
  }
  
  @Check
  public void checkJoinTable(final Reference ref) {
    String _databaseJoinTable = ref.getDatabaseJoinTable();
    boolean _tripleEquals = (_databaseJoinTable == null);
    if (_tripleEquals) {
      return;
    }
    if ((this.isBidirectionalManyToMany(ref) && (ref.getOppositeHolder().getOpposite().getDatabaseJoinTable() != null))) {
      this.warning("Define databaseJoinTable only at one side of the many-to-many association", 
        TacticdslPackage.Literals.REFERENCE__DATABASE_JOIN_TABLE);
    }
    boolean _not = (!(this.isBidirectionalManyToMany(ref) || (this.isUnidirectionalToMany(ref) && (!ref.isInverse()))));
    if (_not) {
      this.error("databaseJoinTable is only applicable for bidirectional many-to-many, or unidirectional to-many without inverse", 
        TacticdslPackage.Literals.REFERENCE__DATABASE_JOIN_TABLE);
    }
  }
  
  @Check
  public void checkJoinColumn(final Reference ref) {
    String _databaseJoinColumn = ref.getDatabaseJoinColumn();
    boolean _tripleEquals = (_databaseJoinColumn == null);
    if (_tripleEquals) {
      return;
    }
    boolean _not = (!(this.isUnidirectionalToMany(ref) && (!ref.isInverse())));
    if (_not) {
      this.error("databaseJoinColumn is only applicable for unidirectional to-many without inverse", 
        TacticdslPackage.Literals.REFERENCE__DATABASE_JOIN_COLUMN);
    }
  }
  
  private boolean isUnidirectionalToMany(final Reference ref) {
    return ((!Objects.equal(ref.getCollectionType(), CollectionType.NONE)) && (ref.getOppositeHolder() == null));
  }
  
  private boolean isBidirectionalManyToMany(final Reference ref) {
    return ((((!Objects.equal(ref.getCollectionType(), CollectionType.NONE)) && (ref.getOppositeHolder() != null)) && (ref.getOppositeHolder().getOpposite() != null)) && (!Objects.equal(ref.getOppositeHolder().getOpposite().getCollectionType(), CollectionType.NONE)));
  }
  
  @Check
  public void checkNullable(final Reference ref) {
    if ((ref.isNullable() && (!Objects.equal(ref.getCollectionType(), CollectionType.NONE)))) {
      CollectionType _collectionType = ref.getCollectionType();
      String _plus = ("Nullable isn\'t applicable for references with cardinality many (" + _collectionType);
      String _plus_1 = (_plus + ")");
      this.error(_plus_1, 
        TacticdslPackage.Literals.ANY_PROPERTY__NULLABLE);
    }
  }
  
  /**
   * For bidirectional one-to-many associations it should only be possible to
   * define databaseColumn on the reference pointing to the one-side.
   */
  @Check
  public void checkDatabaseColumnForBidirectionalOneToMany(final Reference ref) {
    String _databaseColumn = ref.getDatabaseColumn();
    boolean _tripleEquals = (_databaseColumn == null);
    if (_tripleEquals) {
      return;
    }
    if (((((!Objects.equal(ref.getCollectionType(), CollectionType.NONE)) && (ref.getOppositeHolder() != null)) && (ref.getOppositeHolder().getOpposite() != null)) && Objects.equal(ref.getOppositeHolder().getOpposite().getCollectionType(), CollectionType.NONE))) {
      this.error("databaseColumn should be defined at the opposite side", TacticdslPackage.Literals.PROPERTY__DATABASE_COLUMN);
    }
  }
  
  @Check
  public void checkOpposite(final Reference ref) {
    if (((ref.getOppositeHolder() == null) || (ref.getOppositeHolder().getOpposite() == null))) {
      return;
    }
    boolean _not = (!((ref.getOppositeHolder().getOpposite().getOppositeHolder() != null) && Objects.equal(ref.getOppositeHolder().getOpposite().getOppositeHolder().getOpposite(), ref)));
    if (_not) {
      String _name = ref.getOppositeHolder().getOpposite().getName();
      String _plus = ("Opposite should specify this reference as opposite: " + _name);
      String _plus_1 = (_plus + " <-> ");
      String _name_1 = ref.getName();
      String _plus_2 = (_plus_1 + _name_1);
      this.error(_plus_2, 
        TacticdslPackage.Literals.REFERENCE__OPPOSITE_HOLDER);
    }
  }
  
  @Check
  public void checkChangeableCollection(final Reference ref) {
    if ((ref.isNotChangeable() && (!Objects.equal(ref.getCollectionType(), CollectionType.NONE)))) {
      this.warning("x-to-many references are never changeable, the content of the collection is always changeable", 
        TacticdslPackage.Literals.ANY_PROPERTY__NOT_CHANGEABLE);
    }
  }
  
  @Check
  public void checkOrderBy(final Reference ref) {
    if (((ref.getOrderBy() != null) && ((!this.isBag(ref)) && (!this.isList(ref))))) {
      this.error("orderBy only applicable for Bag or List collections", TacticdslPackage.Literals.REFERENCE__ORDER_BY);
    }
  }
  
  @Check
  public void checkOrderColumn(final Reference ref) {
    if ((ref.isOrderColumn() && (!this.isList(ref)))) {
      this.error("orderColumn only applicable for List collections", TacticdslPackage.Literals.REFERENCE__ORDER_COLUMN);
    }
  }
  
  @Check
  public void checkOrderByOrOrderColumn(final Reference ref) {
    if (((ref.getOrderBy() != null) && ref.isOrderColumn())) {
      this.error("use either orderBy or orderColumn for List collections", TacticdslPackage.Literals.REFERENCE__ORDER_BY);
    }
  }
  
  private boolean isBag(final Reference ref) {
    CollectionType _collectionType = ref.getCollectionType();
    return Objects.equal(_collectionType, CollectionType.BAG);
  }
  
  private boolean isList(final Reference ref) {
    CollectionType _collectionType = ref.getCollectionType();
    return Objects.equal(_collectionType, CollectionType.LIST);
  }
  
  @Check
  public void checkNullableKey(final Property prop) {
    if ((prop.isKey() && prop.isNullable())) {
      final EObject parent = prop.eContainer();
      boolean _hasAtLeastOneNotNullableKeyElement = this.hasAtLeastOneNotNullableKeyElement(parent);
      boolean _not = (!_hasAtLeastOneNotNullableKeyElement);
      if (_not) {
        this.error("Natural key must not be nullable. Composite keys must have at least one not nullable property.", 
          TacticdslPackage.Literals.ANY_PROPERTY__NULLABLE);
      }
    }
  }
  
  private boolean hasAtLeastOneNotNullableKeyElement(final EObject parent) {
    int keyCount = 0;
    int nullableKeyCount = 0;
    EList _eContents = parent.eContents();
    for (final EObject each : _eContents) {
      if ((each instanceof Attribute)) {
        boolean _isKey = ((Attribute)each).isKey();
        if (_isKey) {
          keyCount = (keyCount + 1);
          boolean _isNullable = ((Attribute)each).isNullable();
          if (_isNullable) {
            nullableKeyCount = (nullableKeyCount + 1);
          }
        }
      } else {
        if ((each instanceof Reference)) {
          boolean _isKey_1 = ((Reference)each).isKey();
          if (_isKey_1) {
            keyCount = (keyCount + 1);
            boolean _isNullable_1 = ((Reference)each).isNullable();
            if (_isNullable_1) {
              nullableKeyCount = (nullableKeyCount + 1);
            }
          }
        } else {
          if ((each instanceof DtoAttribute)) {
            boolean _isKey_2 = ((DtoAttribute)each).isKey();
            if (_isKey_2) {
              keyCount = (keyCount + 1);
              boolean _isNullable_2 = ((DtoAttribute)each).isNullable();
              if (_isNullable_2) {
                nullableKeyCount = (nullableKeyCount + 1);
              }
            }
          } else {
            if ((each instanceof DtoReference)) {
              boolean _isKey_3 = ((DtoReference)each).isKey();
              if (_isKey_3) {
                keyCount = (keyCount + 1);
                boolean _isNullable_3 = ((DtoReference)each).isNullable();
                if (_isNullable_3) {
                  nullableKeyCount = (nullableKeyCount + 1);
                }
              }
            }
          }
        }
      }
    }
    return ((keyCount - nullableKeyCount) >= 1);
  }
  
  @Check
  public void checkKeyNotManyRefererence(final Reference ref) {
    if ((ref.isKey() && (!Objects.equal(ref.getCollectionType(), CollectionType.NONE)))) {
      this.error("Natural key can\'t be a many refererence.", TacticdslPackage.Literals.ANY_PROPERTY__KEY);
    }
  }
  
  @Check
  public void checkCascade(final Reference ref) {
    if (((ref.getCascade() != null) && (ref.getDomainObjectType() instanceof BasicType))) {
      this.error("Cascade is not applicable for BasicType", TacticdslPackage.Literals.REFERENCE__CASCADE);
    }
    if (((ref.getCascade() != null) && (ref.getDomainObjectType() instanceof org.contextmapper.tactic.dsl.tacticdsl.Enum))) {
      this.error("Cascade is not applicable for enum", TacticdslPackage.Literals.REFERENCE__CASCADE);
    }
  }
  
  @Check
  public void checkCache(final Reference ref) {
    if ((ref.isCache() && (ref.getDomainObjectType() instanceof BasicType))) {
      this.error("Cache is not applicable for BasicType", TacticdslPackage.Literals.REFERENCE__CACHE);
    }
    if ((ref.isCache() && (ref.getDomainObjectType() instanceof org.contextmapper.tactic.dsl.tacticdsl.Enum))) {
      this.error("Cache is not applicable for enum", TacticdslPackage.Literals.REFERENCE__CACHE);
    }
  }
  
  @Check
  public void checkRepositoryName(final Repository repository) {
    if (((repository.getName() != null) && (!repository.getName().endsWith("Repository")))) {
      this.error("Name of repository must end with \'Repository\'", TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NAME);
    }
  }
  
  @Check
  public void checkEnumReference(final Reference ref) {
    if (((ref.getDomainObjectType() instanceof org.contextmapper.tactic.dsl.tacticdsl.Enum) && (!Objects.equal(ref.getCollectionType(), CollectionType.NONE)))) {
      final boolean notPersistentVO = ((ref.eContainer() instanceof ValueObject) && ((ValueObject) ref.eContainer()).isNotPersistent());
      if ((!notPersistentVO)) {
        this.error("Collection of enum is not supported", TacticdslPackage.Literals.ANY_PROPERTY__COLLECTION_TYPE);
      }
    }
  }
  
  @Check
  public void checkEnumValues(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    boolean _isEmpty = dslEnum.getValues().isEmpty();
    if (_isEmpty) {
      this.error("At least one enum value must be defined", TacticdslPackage.Literals.ENUM__VALUES);
    }
  }
  
  @Check
  public void checkEnumAttributes(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    boolean _isEmpty = dslEnum.getValues().isEmpty();
    if (_isEmpty) {
      return;
    }
    boolean _isEmpty_1 = dslEnum.getAttributes().isEmpty();
    if (_isEmpty_1) {
      return;
    }
    final int attSize = dslEnum.getAttributes().size();
    EList _values = dslEnum.getValues();
    for (final EnumValue each : _values) {
      int _size = each.getParameters().size();
      boolean _notEquals = (_size != attSize);
      if (_notEquals) {
        this.error("Enum attribute not defined", TacticdslPackage.Literals.ENUM__VALUES);
        return;
      }
    }
  }
  
  @Check
  public void checkEnumParameter(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    boolean _isEmpty = dslEnum.getValues().isEmpty();
    if (_isEmpty) {
      return;
    }
    final int expectedSize = dslEnum.getValues().get(0).getParameters().size();
    EList _values = dslEnum.getValues();
    for (final EnumValue each : _values) {
      int _size = each.getParameters().size();
      boolean _notEquals = (_size != expectedSize);
      if (_notEquals) {
        this.error("Enum values must have same number of parameters", TacticdslPackage.Literals.ENUM__VALUES);
        return;
      }
    }
  }
  
  @Check
  public void checkEnumImplicitAttribute(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    boolean _isEmpty = dslEnum.getValues().isEmpty();
    if (_isEmpty) {
      return;
    }
    boolean _isEmpty_1 = dslEnum.getAttributes().isEmpty();
    boolean _not = (!_isEmpty_1);
    if (_not) {
      return;
    }
    EList _values = dslEnum.getValues();
    for (final EnumValue each : _values) {
      int _size = each.getParameters().size();
      boolean _greaterThan = (_size > 1);
      if (_greaterThan) {
        this.error("Only one implicit value attribute is allowed", TacticdslPackage.Literals.ENUM__VALUES);
        return;
      }
    }
  }
  
  @Check
  public void checkEnumAttributeKey(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    boolean _isEmpty = dslEnum.getValues().isEmpty();
    if (_isEmpty) {
      return;
    }
    int count = 0;
    EList _attributes = dslEnum.getAttributes();
    for (final EnumAttribute each : _attributes) {
      boolean _isKey = each.isKey();
      if (_isKey) {
        count = (count + 1);
      }
    }
    if ((count > 1)) {
      this.error("Only one enum attribute can be defined as key", TacticdslPackage.Literals.ENUM__ATTRIBUTES);
    }
  }
  
  @Check
  public void checkEnumOrdinal(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    final String hint = dslEnum.getHint();
    if (((hint != null) && hint.contains("ordinal"))) {
      EList _attributes = dslEnum.getAttributes();
      for (final EnumAttribute attr : _attributes) {
        boolean _isKey = attr.isKey();
        if (_isKey) {
          this.error("ordinal is not allowed for enums with a key attribute", TacticdslPackage.Literals.ENUM__ATTRIBUTES);
          return;
        }
      }
      EList _values = dslEnum.getValues();
      for (final EnumValue each : _values) {
        if (((each.getParameters().size() == 1) && dslEnum.getAttributes().isEmpty())) {
          this.error("ordinal is not allowed for enum with implicit value", TacticdslPackage.Literals.ENUM__VALUES);
          return;
        }
      }
    }
  }
  
  @Check
  public void checkEnumOrdinalOrDatabaseLength(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    final String hint = dslEnum.getHint();
    if ((((hint != null) && hint.contains("ordinal")) && hint.contains("databaseLength"))) {
      this.error("ordinal in combination with databaseLength is not allowed", TacticdslPackage.Literals.ENUM__ATTRIBUTES);
    }
  }
  
  @Check
  public void checkEnumDatabaseLength(final org.contextmapper.tactic.dsl.tacticdsl.Enum dslEnum) {
    final String hint = dslEnum.getHint();
    if (((hint != null) && hint.contains("databaseLength"))) {
      EList _attributes = dslEnum.getAttributes();
      for (final EnumAttribute attr : _attributes) {
        if ((attr.isKey() && (!attr.getType().equals("String")))) {
          this.error("databaseLength is not allowed for enums not having a key of type String", TacticdslPackage.Literals.ENUM__ATTRIBUTES);
          return;
        }
      }
    }
  }
  
  @Check
  public void checkGap(final Service service) {
    if ((service.isGapClass() && service.isNoGapClass())) {
      this.error("Unclear specification of gap", TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NO_GAP_CLASS);
    }
  }
  
  @Check
  public void checkGap(final Repository repository) {
    if ((repository.isGapClass() && repository.isNoGapClass())) {
      this.error("Unclear specification of gap", TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NO_GAP_CLASS);
    }
  }
  
  @Check
  public void checkGap(final DomainObject domainObj) {
    if ((domainObj.isGapClass() && domainObj.isNoGapClass())) {
      this.error("Unclear specification of gap", TacticdslPackage.Literals.DOMAIN_OBJECT__NO_GAP_CLASS);
    }
  }
  
  @Check
  public void checkGap(final BasicType domainObj) {
    if ((domainObj.isGapClass() && domainObj.isNoGapClass())) {
      this.error("Unclear specification of gap", TacticdslPackage.Literals.BASIC_TYPE__NO_GAP_CLASS);
    }
  }
  
  @Check
  public void checkDiscriminatorValue(final Entity domainObj) {
    if (((domainObj.getDiscriminatorValue() != null) && (domainObj.getExtends() == null))) {
      this.error("discriminatorValue can only be used when you extend another Entity", 
        TacticdslPackage.Literals.DOMAIN_OBJECT__DISCRIMINATOR_VALUE);
    }
  }
  
  @Check
  public void checkDiscriminatorValue(final ValueObject domainObj) {
    if (((domainObj.getDiscriminatorValue() != null) && (domainObj.getExtends() == null))) {
      this.error("discriminatorValue can only be used when you extend another ValueObject", 
        TacticdslPackage.Literals.DOMAIN_OBJECT__DISCRIMINATOR_VALUE);
    }
  }
  
  @Check
  public void checkRepositoryOnlyForAggregateRoot(final DomainObject domainObj) {
    if (((domainObj.getRepository() != null) && (!domainObj.isAggregateRoot()))) {
      this.error("Only aggregate roots can have Repository", TacticdslPackage.Literals.DOMAIN_OBJECT__REPOSITORY);
    }
  }
  
  @Check
  public void checkBelongsToRefersToAggregateRoot(final DomainObject domainObj) {
    if (((domainObj.getBelongsTo() != null) && (!domainObj.getBelongsTo().isAggregateRoot()))) {
      this.error("belongsTo should refer to the aggregate root DomainObject", TacticdslPackage.Literals.DOMAIN_OBJECT__BELONGS_TO);
    }
  }
  
  @Check
  public void checkAggregateRootOnlyForPersistentValueObject(final ValueObject domainObj) {
    if ((domainObj.isAggregateRoot() && domainObj.isNotPersistent())) {
      this.error("aggregateRoot is only applicable for persistent ValueObjects", 
        TacticdslPackage.Literals.DOMAIN_OBJECT__AGGREGATE_ROOT);
    }
  }
  
  @Check
  public void checkLength(final Attribute attr) {
    String _length = attr.getLength();
    boolean _tripleEquals = (_length == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isString = this.isString(attr);
    boolean _not = (!_isString);
    if (_not) {
      this.error("length is only relevant for strings", TacticdslPackage.Literals.ATTRIBUTE__LENGTH);
    }
    boolean _matches = this.DIGITS_PATTERN.matcher(attr.getLength()).matches();
    boolean _not_1 = (!_matches);
    if (_not_1) {
      this.error("length value should be numeric, e.g. length = \"10\"", TacticdslPackage.Literals.ATTRIBUTE__LENGTH);
    }
  }
  
  @Check
  public void checkNullable(final Attribute attr) {
    if ((attr.isNullable() && this.isPrimitive(attr))) {
      this.error("nullable is not relevant for primitive types", TacticdslPackage.Literals.ANY_PROPERTY__NULLABLE);
    }
  }
  
  @Check
  public void checkCreditCardNumber(final Attribute attr) {
    if ((attr.isCreditCardNumber() && (!this.isString(attr)))) {
      this.error("creditCardNumber is only relevant for strings", TacticdslPackage.Literals.ATTRIBUTE__CREDIT_CARD_NUMBER);
    }
  }
  
  @Check
  public void checkEmail(final Attribute attr) {
    if ((attr.isEmail() && (!this.isString(attr)))) {
      this.error("email is only relevant for strings", TacticdslPackage.Literals.ATTRIBUTE__EMAIL);
    }
  }
  
  @Check
  public void checkNotEmpty(final Attribute attr) {
    if ((attr.isNotEmpty() && (!(this.isString(attr) || this.isCollection(attr))))) {
      this.error("notEmpty is only relevant for strings or collection types", TacticdslPackage.Literals.ANY_PROPERTY__NOT_EMPTY);
    }
  }
  
  @Check
  public void checkNotEmpty(final Reference ref) {
    if ((ref.isNotEmpty() && (!this.isCollection(ref)))) {
      this.error("notEmpty is only relevant for collection types", TacticdslPackage.Literals.ANY_PROPERTY__NOT_EMPTY);
    }
  }
  
  @Check
  public void checkSize(final Reference ref) {
    String _size = ref.getSize();
    boolean _tripleEquals = (_size == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isCollection = this.isCollection(ref);
    boolean _not = (!_isCollection);
    if (_not) {
      this.error("size is only relevant for collection types", TacticdslPackage.Literals.ANY_PROPERTY__SIZE);
    }
  }
  
  @Check
  public void checkPast(final Attribute attr) {
    if ((attr.isPast() && (!this.isTemporal(attr)))) {
      this.error("past is only relevant for temporal types", TacticdslPackage.Literals.ATTRIBUTE__PAST);
    }
  }
  
  @Check
  public void checkFuture(final Attribute attr) {
    if ((attr.isFuture() && (!this.isTemporal(attr)))) {
      this.error("future is only relevant for temporal types", TacticdslPackage.Literals.ATTRIBUTE__FUTURE);
    }
  }
  
  @Check
  public void checkMin(final Attribute attr) {
    String _min = attr.getMin();
    boolean _tripleEquals = (_min == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isNumeric = this.isNumeric(attr);
    boolean _not = (!_isNumeric);
    if (_not) {
      this.error("min is only relevant for numeric types", TacticdslPackage.Literals.ATTRIBUTE__MIN);
    }
  }
  
  @Check
  public void checkMax(final Attribute attr) {
    String _max = attr.getMax();
    boolean _tripleEquals = (_max == null);
    if (_tripleEquals) {
      return;
    }
    boolean _isNumeric = this.isNumeric(attr);
    boolean _not = (!_isNumeric);
    if (_not) {
      this.error("max is only relevant for numeric types", TacticdslPackage.Literals.ATTRIBUTE__MAX);
    }
  }
  
  @Check
  public void checkRange(final Attribute attr) {
    if (((attr.getRange() != null) && (!this.isNumeric(attr)))) {
      this.error("range is only relevant for numeric types", TacticdslPackage.Literals.ATTRIBUTE__RANGE);
    }
  }
  
  @Check
  public void checkDigits(final Attribute attr) {
    if (((attr.getDigits() != null) && (!this.isNumeric(attr)))) {
      this.error("digits is only relevant for numeric types", TacticdslPackage.Literals.ATTRIBUTE__DIGITS);
    }
  }
  
  @Check
  public void checkAssertTrue(final Attribute attr) {
    if ((attr.isAssertTrue() && (!this.isBoolean(attr)))) {
      this.error("assertTrue is only relevant for boolean types", TacticdslPackage.Literals.ATTRIBUTE__ASSERT_TRUE);
    }
  }
  
  @Check
  public void checkAssertFalse(final Attribute attr) {
    if ((attr.isAssertFalse() && (!this.isBoolean(attr)))) {
      this.error("assertFalse is only relevant for boolean types", TacticdslPackage.Literals.ATTRIBUTE__ASSERT_FALSE);
    }
  }
  
  @Check
  public void checkScaffoldValueObject(final ValueObject valueObj) {
    if ((valueObj.isScaffold() && valueObj.isNotPersistent())) {
      this.error("Scaffold not useful for not-persistent ValueObject.", TacticdslPackage.Literals.DOMAIN_OBJECT__SCAFFOLD);
    }
  }
  
  @Check
  public void checkScaffoldEvent(final Event event) {
    if ((event.isScaffold() && (!event.isPersistent()))) {
      this.error("Scaffold not useful for not-persistent event.", TacticdslPackage.Literals.DOMAIN_OBJECT__SCAFFOLD, IssueCodes.NON_PERSISTENT_EVENT, 
        TacticdslPackage.Literals.DOMAIN_OBJECT__SCAFFOLD.getName());
    }
  }
  
  @Check
  public void checkRepositoryEvent(final Event event) {
    if (((event.getRepository() != null) && (!event.isPersistent()))) {
      this.error("Repository not useful for not-persistent event.", TacticdslPackage.Literals.DOMAIN_OBJECT__REPOSITORY, 
        IssueCodes.NON_PERSISTENT_EVENT, TacticdslPackage.Literals.DOMAIN_OBJECT__REPOSITORY.getName());
    }
  }
  
  private boolean isString(final Attribute attribute) {
    return ("String".equals(attribute.getType()) && (!this.isCollection(attribute)));
  }
  
  private boolean isCollection(final Attribute attribute) {
    return ((attribute.getCollectionType() != null) && (!Objects.equal(attribute.getCollectionType(), CollectionType.NONE)));
  }
  
  private boolean isCollection(final Reference ref) {
    return ((ref.getCollectionType() != null) && (!Objects.equal(ref.getCollectionType(), CollectionType.NONE)));
  }
  
  private boolean isPrimitive(final Attribute attribute) {
    return (this.SUPPORTED_PRIMITIVE_TYPES.contains(attribute.getType()) && (!this.isCollection(attribute)));
  }
  
  private boolean isTemporal(final Attribute attribute) {
    return (this.SUPPORTED_TEMPORAL_TYPES.contains(attribute.getType()) && (!this.isCollection(attribute)));
  }
  
  private boolean isNumeric(final Attribute attribute) {
    return (this.SUPPORTED_NUMERIC_TYPES.contains(attribute.getType()) && (!this.isCollection(attribute)));
  }
  
  private boolean isBoolean(final Attribute attribute) {
    return (this.SUPPORTED_BOOLEAN_TYPES.contains(attribute.getType()) && (!this.isCollection(attribute)));
  }
  
  @Check
  public void checkRepositoryDuplicateName(final Repository repository) {
    if (((repository.getName() != null) && (IteratorExtensions.size(IteratorExtensions.filter(TacticDslExtensions.eAllOfClass(EcoreUtil.getRootContainer(repository), Repository.class), ((Function1) (Repository it) -> {
      String _name = it.getName();
      String _name_1 = repository.getName();
      return Boolean.valueOf(Objects.equal(_name, _name_1));
    }))) > 1))) {
      String _name = repository.getName();
      String _plus = ("Duplicate name.  There is already an existing Repository named \'" + _name);
      String _plus_1 = (_plus + "\'.");
      this.error(_plus_1, TacticdslPackage.Literals.SERVICE_REPOSITORY_OPTION__NAME, repository.getName());
    }
  }
  
  /**
   * Type matches a domain object, but due to missing '-', comes in as a Attribute rather than a Reference
   */
  @Check
  public void checkMissingReferenceNotationWithNoCollection(final Attribute attr) {
    if ((((attr.getType() != null) && Objects.equal(attr.getCollectionType(), CollectionType.NONE)) && 
      (IterableExtensions.isEmpty(TacticDslExtensions.domainObjectsForAttributeType(attr)) == false))) {
      String _type = attr.getType();
      String _plus = ("Use - " + _type);
      this.warning(_plus, TacticdslPackage.Literals.ATTRIBUTE__TYPE, attr.getType());
    }
  }
  
  /**
   * Type for collection matches a domain object, but due to missing '-', comes in as a Attribute rather than a Reference
   */
  @Check
  public void checkMissingReferenceNotationWithCollection(final Attribute attr) {
    if ((((attr.getType() != null) && (!Objects.equal(attr.getCollectionType(), CollectionType.NONE))) && 
      (IterableExtensions.isEmpty(TacticDslExtensions.domainObjectsForAttributeType(attr)) == false))) {
      CollectionType _collectionType = attr.getCollectionType();
      String _plus = ("Use - " + _collectionType);
      String _plus_1 = (_plus + "<");
      String _type = attr.getType();
      String _plus_2 = (_plus_1 + _type);
      String _plus_3 = (_plus_2 + ">");
      this.warning(_plus_3, TacticdslPackage.Literals.ATTRIBUTE__TYPE, attr.getType());
    }
  }
  
  @Check
  public void checkMissingDomainObjectInServiceOperationReturnType(final ServiceOperation it) {
    if (((((it.getReturnType() != null) && (it.getReturnType().getDomainObjectType() == null)) && (it.getReturnType().getType() != null)) && 
      (TacticDslExtensions.firstDomainObjectForType(it.getReturnType()) != null))) {
      String _type = it.getReturnType().getType();
      String _plus = ("Use @" + _type);
      this.warning(_plus, TacticdslPackage.Literals.SERVICE_OPERATION__RETURN_TYPE, it.getReturnType().getType());
    }
  }
  
  @Check
  public void checkMissingDomainObjectInRepositoryOperationReturnType(final RepositoryOperation it) {
    if (((((it.getReturnType() != null) && (it.getReturnType().getDomainObjectType() == null)) && (it.getReturnType().getType() != null)) && 
      (TacticDslExtensions.firstDomainObjectForType(it.getReturnType()) != null))) {
      String _type = it.getReturnType().getType();
      String _plus = ("Use @" + _type);
      this.warning(_plus, TacticdslPackage.Literals.REPOSITORY_OPERATION__RETURN_TYPE, it.getReturnType().getType());
    }
  }
  
  @Check
  public void checkMissingDomainObjectInParameter(final Parameter it) {
    if (((((it.getParameterType() != null) && (it.getParameterType().getDomainObjectType() == null)) && (it.getParameterType().getType() != null)) && 
      (TacticDslExtensions.firstDomainObjectForType(it.getParameterType()) != null))) {
      String _type = it.getParameterType().getType();
      String _plus = ("Use @" + _type);
      this.warning(_plus, TacticdslPackage.Literals.PARAMETER__PARAMETER_TYPE, it.getParameterType().getType());
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy