ReqSpecValidator.java

/**
 * Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
 * All Rights Reserved.
 * 
 * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
 * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
 * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 * 
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
 * 
 * This program includes and/or can make use of certain third party source code, object code, documentation and other
 * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
 * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
 * conditions contained in any such Third Party Software or separate license file distributed with such Third Party
 * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
 * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
 * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
 */
package org.osate.reqspec.validation;

import com.google.common.base.Objects;
import com.google.inject.Inject;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
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.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.osate.aadl2.Classifier;
import org.osate.aadl2.ComponentClassifier;
import org.osate.aadl2.ComponentImplementation;
import org.osate.aadl2.ComponentType;
import org.osate.aadl2.Feature;
import org.osate.aadl2.NamedElement;
import org.osate.aadl2.SystemImplementation;
import org.osate.alisa.common.common.TargetType;
import org.osate.alisa.common.util.CommonUtilExtension;
import org.osate.pluginsupport.ExecuteJavaUtil;
import org.osate.reqspec.reqSpec.ContractualElement;
import org.osate.reqspec.reqSpec.DocumentSection;
import org.osate.reqspec.reqSpec.GlobalConstants;
import org.osate.reqspec.reqSpec.GlobalRequirementSet;
import org.osate.reqspec.reqSpec.Goal;
import org.osate.reqspec.reqSpec.IncludeGlobalRequirement;
import org.osate.reqspec.reqSpec.ReqDocument;
import org.osate.reqspec.reqSpec.ReqSpec;
import org.osate.reqspec.reqSpec.ReqSpecPackage;
import org.osate.reqspec.reqSpec.Requirement;
import org.osate.reqspec.reqSpec.RequirementSet;
import org.osate.reqspec.reqSpec.StakeholderGoals;
import org.osate.reqspec.reqSpec.SystemRequirementSet;
import org.osate.reqspec.reqSpec.WhenCondition;
import org.osate.reqspec.util.IReqspecGlobalReferenceFinder;
import org.osate.reqspec.util.ReqSpecUtilExtension;

/**
 * Custom validation rules.
 * 
 * see http://www.eclipse.org/Xtext/documentation.html#validation
 */
@SuppressWarnings("all")
public class ReqSpecValidator extends AbstractReqSpecValidator {
  public static final String MISSING_STAKEHOLDER = "missingStakeholder";

  public static final String MISSING_STAKEHOLDER_GOAL = "missingStakeholderGoal";

  public static final String MULTIPLE_CLASSIFIERS = "multipleClassifiers";

  public static final String FEATURES_WITHOUT_REQUIREMENT = "featuresWithoutRequirement";

  public static final String DUPLICATE_GOAL_WITHIN_STAKEHOLDER_GOALS = "org.osate.reqspec.validation.duplicate.goal.within.stakeholdergoals";

  public static final String DUPLICATE_STAKEHOLDER_GOALS = "org.osate.reqspec.validation.duplicate.stakeholdergoals";

  public static final String REQSPEC_FOR_DIFFERS_FROM_STAKEHOLDERGOALS_FOR = "org.osate.reqspec.validation.reqspec.for.differs.from.stakeholdergoals.for";

  public static final String GOAL_REFERENCE_NOT_FOUND = "org.osate.reqspec.validation.goal.reference.not.found";

  public static final String DUPLICATE_REQUIREMENTS = "org.osate.reqspec.validation.duplicate.requirements";

  public static final String DUPLICATE_REQUIREMENT_WITHIN_REQUIREMENTS = "org.osate.reqspec.validation.duplicate.requirement.within.requirements";

  public static final String CYCLE_IN_GOAL_REFINE_HIERARCHY = "org.osate.reqspec.validation.cycle.in.goal.refine.hierarchy";

  public static final String CYCLE_IN_REQUIREMENT_REFINE_HIERARCHY = "org.osate.reqspec.validation.cycle.in.requirement.refine.hierarchy";

  public static final String ILLEGAL_OBJECT_FOR_FILETYPE_IN_DOCUMENTSECTION = "org.osate.reqspec.validation.illegal.object.for.filetype.in.documentsection";

  public static final String ILLEGAL_OBJECT_FOR_FILETYPE_IN_REQSPEC = "org.osate.reqspec.validation.illegal.object.for.filetype.in.reqspec";

  public static final String ILLEGAL_OBJECT_FOR_FILETYPE_IN_REQDOCUMENT = "org.osate.reqspec.validation.illegal.object.for.filetype.in.reqdocument";

  public static final String REQSPEC_FILE_EXT = "reqspec";

  public static final String GOALS_FILE_EXT = "goals";

  public static final String REQDOC_FILE_EXT = "reqdoc";

  public static final String GOALDOC_FILE_EXT = "goaldoc";

  public static final String CONSTANTS_FILE_EXT = "constants";

  public static final String INCORRECT_GLOBAL_REQUIREMENT_INCLUDE = "org.osate.reqspec.validation.incorrect.global.requirement.include";

  public static final String CONDITION_METHOD_NOT_FOUND = "org.osate.reqspec.validation.condition.method.not.found";

  public static final String DUPLICATE_GLOBALREQUIREMENTS = "org.osate.reqspec.validation.duplicate.globalrequirements";

  public static final String ELEMENT_TARGETTYPE = "org.osate.reqspec.validation.element.targettype";

  @Check
  public void checkMissingStakeholder(final Goal goal) {
    if ((goal.getStakeholderReference().isEmpty() && goal.getRefinesReference().isEmpty())) {
      this.warning("Goal should have stakeholders", ReqSpecPackage.Literals.GOAL__STAKEHOLDER_REFERENCE, 
        ReqSpecValidator.MISSING_STAKEHOLDER);
    }
  }

  @Check
  public void checkMissingGoal(final Requirement req) {
    if ((req.getGoalReference().isEmpty() && req.getRefinesReference().isEmpty())) {
      this.warning("System requirement should have stakeholder goal or requirement reference", 
        ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__GOAL_REFERENCE, ReqSpecValidator.MISSING_STAKEHOLDER_GOAL);
    }
  }

  @Check
  public void checkMultipleSystems(final ReqDocument reqdoc) {
    final BasicEList<Classifier> syslist = new BasicEList<Classifier>();
    final Consumer<EObject> _function = (EObject e) -> {
      if ((e instanceof ContractualElement)) {
        ComponentClassifier _targetClassifier = ReqSpecUtilExtension.targetClassifier(((ContractualElement)e));
        syslist.add(_targetClassifier);
      }
    };
    reqdoc.getContent().forEach(_function);
    int _size = syslist.size();
    boolean _greaterThan = (_size > 1);
    if (_greaterThan) {
      final Function1<Classifier, String> _function_1 = (Classifier it) -> {
        return it.getName();
      };
      final Function2<String, String, String> _function_2 = (String p1, String p2) -> {
        return ((p1 + " ") + p2);
      };
      final String cls = IterableExtensions.<String>reduce(ListExtensions.<Classifier, String>map(syslist, _function_1), _function_2);
      this.warning(("Requirements cover multiple classifiers: " + cls), ReqSpecPackage.Literals.REQ_DOCUMENT__CONTENT, 
        ReqSpecValidator.MULTIPLE_CLASSIFIERS);
    }
  }

  @Check
  public void checkMultipleSystems(final DocumentSection docsection) {
    final BasicEList<Classifier> syslist = new BasicEList<Classifier>();
    final Consumer<EObject> _function = (EObject e) -> {
      if ((e instanceof ContractualElement)) {
        ComponentClassifier _targetClassifier = ReqSpecUtilExtension.targetClassifier(((ContractualElement)e));
        syslist.add(_targetClassifier);
      }
    };
    docsection.getContent().forEach(_function);
    boolean _isEmpty = syslist.isEmpty();
    boolean _not = (!_isEmpty);
    if (_not) {
      final Function1<Classifier, String> _function_1 = (Classifier it) -> {
        return it.getName();
      };
      final Function2<String, String, String> _function_2 = (String p1, String p2) -> {
        return ((p1 + " ") + p2);
      };
      final String cls = IterableExtensions.<String>reduce(ListExtensions.<Classifier, String>map(syslist, _function_1), _function_2);
      this.warning(("Requirements cover multiple classifiers: " + cls), 
        ReqSpecPackage.Literals.DOCUMENT_SECTION__CONTENT, ReqSpecValidator.MULTIPLE_CLASSIFIERS);
    }
  }

  @Check
  public void checkFeatureCoverage(final SystemRequirementSet sysreqs) {
    final ComponentClassifier cl = sysreqs.getTarget();
    if (((cl == null) || cl.getAllFeatures().isEmpty())) {
      return;
    }
    final BasicEList<NamedElement> fealist = new BasicEList<NamedElement>();
    final Consumer<Feature> _function = (Feature e) -> {
      final Function1<Requirement, Boolean> _function_1 = (Requirement r) -> {
        NamedElement _targetElement = r.getTargetElement();
        return Boolean.valueOf(Objects.equal(_targetElement, e));
      };
      boolean _exists = IterableExtensions.<Requirement>exists(sysreqs.getRequirements(), _function_1);
      boolean _not = (!_exists);
      if (_not) {
        fealist.add(e);
      }
    };
    cl.getAllFeatures().forEach(_function);
    boolean _isEmpty = fealist.isEmpty();
    boolean _not = (!_isEmpty);
    if (_not) {
      final Function1<NamedElement, String> _function_1 = (NamedElement it) -> {
        return it.getName();
      };
      final Function2<String, String, String> _function_2 = (String p1, String p2) -> {
        return ((p1 + " ") + p2);
      };
      final String fls = IterableExtensions.<String>reduce(ListExtensions.<NamedElement, String>map(fealist, _function_1), _function_2);
      this.warning(("Features without requirement: " + fls), ReqSpecPackage.Literals.REQUIREMENT_SET__REQUIREMENTS, 
        ReqSpecValidator.FEATURES_WITHOUT_REQUIREMENT);
    }
  }

  @Check
  public void checkDuplicateGoal(final StakeholderGoals stakeHolderGoals) {
    final Consumer<Goal> _function = (Goal goal) -> {
      final Function1<Goal, Boolean> _function_1 = (Goal it) -> {
        String _name = it.getName();
        String _name_1 = goal.getName();
        return Boolean.valueOf(Objects.equal(_name, _name_1));
      };
      int _size = IterableExtensions.size(IterableExtensions.<Goal>filter(stakeHolderGoals.getGoals(), _function_1));
      boolean _greaterThan = (_size > 1);
      if (_greaterThan) {
        String _name = goal.getName();
        String _plus = ("Duplicate goal name \'" + _name);
        String _plus_1 = (_plus + "\' in StakeholderGoals \'");
        String _name_1 = stakeHolderGoals.getName();
        String _plus_2 = (_plus_1 + _name_1);
        String _plus_3 = (_plus_2 + "\'");
        this.error(_plus_3, goal, 
          ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__NAME, 
          ReqSpecValidator.DUPLICATE_GOAL_WITHIN_STAKEHOLDER_GOALS, 
          EcoreUtil.getURI(stakeHolderGoals).toString());
      }
    };
    stakeHolderGoals.getGoals().forEach(_function);
  }

  @Check
  public void checkDuplicateRequirement(final RequirementSet sysReq) {
    final Consumer<Requirement> _function = (Requirement requirement) -> {
      final Function1<Requirement, Boolean> _function_1 = (Requirement it) -> {
        String _name = it.getName();
        String _name_1 = requirement.getName();
        return Boolean.valueOf(Objects.equal(_name, _name_1));
      };
      int _size = IterableExtensions.size(IterableExtensions.<Requirement>filter(sysReq.getRequirements(), _function_1));
      boolean _greaterThan = (_size > 1);
      if (_greaterThan) {
        String _name = requirement.getName();
        String _plus = ("Duplicate requirement name \'" + _name);
        String _plus_1 = (_plus + "\' in requirements \'");
        String _name_1 = sysReq.getName();
        String _plus_2 = (_plus_1 + _name_1);
        String _plus_3 = (_plus_2 + "\'");
        this.error(_plus_3, requirement, 
          ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__NAME, 
          ReqSpecValidator.DUPLICATE_REQUIREMENT_WITHIN_REQUIREMENTS, 
          EcoreUtil.getURI(sysReq).toString());
      }
    };
    sysReq.getRequirements().forEach(_function);
  }

  @Check
  public void checkSpecGoalTargetConsistency(final SystemRequirementSet sysReqs) {
    final ComponentClassifier reqSpecTarget = sysReqs.getTarget();
    final EList<Requirement> requirements = sysReqs.getRequirements();
    final Resource resource = sysReqs.eResource();
    final Consumer<Requirement> _function = (Requirement requirement) -> {
      final EList<Goal> goalReferences = requirement.getGoalReference();
      final Consumer<Goal> _function_1 = (Goal goalRef) -> {
        EObject _switchResult = null;
        boolean _matched = false;
        boolean _eIsProxy = goalRef.eIsProxy();
        boolean _not = (!_eIsProxy);
        if (_not) {
          _matched=true;
          _switchResult = goalRef;
        }
        if (!_matched) {
          if ((goalRef.eIsProxy() && EcoreUtil.resolve(goalRef, resource.getResourceSet()).eIsProxy())) {
            _matched=true;
            _switchResult = null;
          }
        }
        if (!_matched) {
          _switchResult = EcoreUtil.resolve(goalRef, resource.getResourceSet());
        }
        final Goal goalRefResolved = ((Goal) _switchResult);
        if ((((goalRefResolved != null) && (ReqSpecUtilExtension.targetClassifier(goalRefResolved) != null)) && 
          (!CommonUtilExtension.isSameorExtends(reqSpecTarget, ReqSpecUtilExtension.targetClassifier(goalRefResolved))))) {
          final String goalTargetName = ReqSpecUtilExtension.targetClassifier(goalRefResolved).getName();
          final String goalTargetURI = EcoreUtil.getURI(ReqSpecUtilExtension.targetClassifier(goalRefResolved)).toString();
          String _name = sysReqs.getName();
          String _plus = ("System Requirement \'" + _name);
          String _plus_1 = (_plus + 
            "\' is not for the same component as the StakeholderGoals that ");
          String _plus_2 = (_plus_1 + 
            "holds the goal that corresponds to requirement \'");
          String _name_1 = requirement.getName();
          String _plus_3 = (_plus_2 + _name_1);
          String _plus_4 = (_plus_3 + "\'");
          this.error(_plus_4, sysReqs, 
            ReqSpecPackage.Literals.SYSTEM_REQUIREMENT_SET__TARGET, 
            ReqSpecValidator.REQSPEC_FOR_DIFFERS_FROM_STAKEHOLDERGOALS_FOR, sysReqs.getTarget().getName(), goalTargetName, goalTargetURI);
        }
      };
      goalReferences.forEach(_function_1);
    };
    requirements.forEach(_function);
  }

  @Check
  public void checkGoalForCycles(final Goal goal) {
    final ArrayList<Goal> goalList = new ArrayList<Goal>();
    goalList.add(goal);
    final Procedure2<Goal, Integer> _function = (Goal refinedGoal, Integer index) -> {
      goalList.add(refinedGoal);
      boolean _checkGoalForCycles = this.checkGoalForCycles(refinedGoal, goalList);
      if (_checkGoalForCycles) {
        String _name = goal.getName();
        String _plus = ("A circular dependency or dependencies exists in the \'refined\' hierarchy of " + _name);
        String _plus_1 = (_plus + 
          ".");
        this.error(_plus_1, goal, ReqSpecPackage.Literals.GOAL__REFINES_REFERENCE, (index).intValue(), ReqSpecValidator.CYCLE_IN_GOAL_REFINE_HIERARCHY, 
          refinedGoal.getName(), EcoreUtil.getURI(refinedGoal).toString());
      }
      int _size = goalList.size();
      int _minus = (_size - 1);
      goalList.remove(_minus);
    };
    IterableExtensions.<Goal>forEach(goal.getRefinesReference(), _function);
  }

  private boolean checkGoalForCycles(final Goal goal, final List<Goal> goalList) {
    boolean _xblockexpression = false;
    {
      final EList<Goal> refinedGoals = goal.getRefinesReference();
      _xblockexpression = (IterableExtensions.<Goal>exists(refinedGoals, ((Function1<Goal, Boolean>) (Goal refinedGoal) -> {
        return Boolean.valueOf(goalList.contains(refinedGoal));
      })) || IterableExtensions.<Goal>exists(refinedGoals, ((Function1<Goal, Boolean>) (Goal refinedGoal) -> {
        goalList.add(refinedGoal);
        final boolean cycles = this.checkGoalForCycles(refinedGoal, goalList);
        int _size = goalList.size();
        int _minus = (_size - 1);
        goalList.remove(_minus);
        return Boolean.valueOf(cycles);
      })));
    }
    return _xblockexpression;
  }

  @Check
  public void checkRequirementTargetType(final Requirement requirement) {
    TargetType _targetType = requirement.getTargetType();
    boolean _tripleEquals = (_targetType == TargetType.ELEMENT);
    if (_tripleEquals) {
      this.error("Target type of global requirement cannot be \'element\'", requirement, 
        ReqSpecPackage.Literals.REQUIREMENT__TARGET_TYPE, ReqSpecValidator.ELEMENT_TARGETTYPE);
    }
  }

  @Check
  public void checkRequirementForCycles(final Requirement requirement) {
    final ArrayList<Requirement> reqList = new ArrayList<Requirement>();
    reqList.add(requirement);
    final Procedure2<Requirement, Integer> _function = (Requirement refinedReq, Integer index) -> {
      reqList.add(refinedReq);
      boolean _checkRequirementForCycles = this.checkRequirementForCycles(refinedReq, reqList);
      if (_checkRequirementForCycles) {
        String _name = requirement.getName();
        String _plus = ("A circular dependency or dependencies exists in the \'refined\' hierarchy of " + _name);
        String _plus_1 = (_plus + ".");
        this.error(_plus_1, requirement, 
          ReqSpecPackage.Literals.REQUIREMENT__REFINES_REFERENCE, (index).intValue(), 
          ReqSpecValidator.CYCLE_IN_REQUIREMENT_REFINE_HIERARCHY, refinedReq.getName(), EcoreUtil.getURI(refinedReq).toString());
      }
      int _size = reqList.size();
      int _minus = (_size - 1);
      reqList.remove(_minus);
    };
    IterableExtensions.<Requirement>forEach(requirement.getRefinesReference(), _function);
  }

  private boolean checkRequirementForCycles(final Requirement requirement, final List<Requirement> reqList) {
    boolean _xblockexpression = false;
    {
      final EList<Requirement> refinedReqs = requirement.getRefinesReference();
      _xblockexpression = (IterableExtensions.<Requirement>exists(refinedReqs, ((Function1<Requirement, Boolean>) (Requirement refinedReq) -> {
        return Boolean.valueOf(reqList.contains(refinedReq));
      })) || IterableExtensions.<Requirement>exists(refinedReqs, ((Function1<Requirement, Boolean>) (Requirement refinedReq) -> {
        reqList.add(refinedReq);
        final boolean cycles = this.checkRequirementForCycles(refinedReq, reqList);
        int _size = reqList.size();
        int _minus = (_size - 1);
        reqList.remove(_minus);
        return Boolean.valueOf(cycles);
      })));
    }
    return _xblockexpression;
  }

  @Inject
  private IReqspecGlobalReferenceFinder reqSpecrefFinder;

  @Check
  public void checkCoverage(final StakeholderGoals shgs) {
    final ComponentClassifier target = shgs.getTarget();
    boolean _isInstance = SystemImplementation.class.isInstance(target);
    boolean _not = (!_isInstance);
    if (_not) {
      return;
    }
    final Iterable<SystemRequirementSet> sysReqs = this.reqSpecrefFinder.getSystemRequirementSets(target);
    final Consumer<Goal> _function = (Goal goal) -> {
      final Function1<SystemRequirementSet, Boolean> _function_1 = (SystemRequirementSet sysReq) -> {
        final Function1<Requirement, Boolean> _function_2 = (Requirement it) -> {
          final Function1<Goal, Boolean> _function_3 = (Goal goalRef) -> {
            return Boolean.valueOf((goalRef == goal));
          };
          return Boolean.valueOf(IterableExtensions.<Goal>exists(it.getGoalReference(), _function_3));
        };
        return Boolean.valueOf(IterableExtensions.<Requirement>exists(sysReq.getRequirements(), _function_2));
      };
      boolean _exists = IterableExtensions.<SystemRequirementSet>exists(sysReqs, _function_1);
      boolean _not_1 = (!_exists);
      if (_not_1) {
        String _name = goal.getName();
        String _plus = ("Goal " + _name);
        String _plus_1 = (_plus + " does not have a corresponding System Requirement.");
        this.error(_plus_1, goal, 
          ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__NAME);
      }
    };
    shgs.getGoals().forEach(_function);
  }

  @Check
  public void checkFileTypeContents(final ReqSpec reqSpec) {
    final URI reqSpecURI = EcoreUtil.getURI(reqSpec);
    final String fileExt = reqSpecURI.fileExtension().toLowerCase();
    final EList<EObject> parts = reqSpec.getParts();
    if (fileExt != null) {
      switch (fileExt) {
        case ReqSpecValidator.REQSPEC_FILE_EXT:
          final Consumer<EObject> _function = (EObject part) -> {
            boolean _matched = false;
            if (part instanceof SystemRequirementSet) {
              _matched=true;
            }
            if (!_matched) {
              if (part instanceof GlobalRequirementSet) {
                _matched=true;
              }
            }
            if (!_matched) {
              if (part instanceof GlobalConstants) {
                _matched=true;
                this.fileTypeWarning(fileExt, "constants", part);
              }
            }
            if (!_matched) {
              this.fileTypeWarning(fileExt, part.getClass().getName(), part);
            }
          };
          parts.forEach(_function);
          break;
        case ReqSpecValidator.GOALS_FILE_EXT:
          final Consumer<EObject> _function_1 = (EObject part) -> {
            boolean _matched = false;
            if (part instanceof StakeholderGoals) {
              _matched=true;
            }
            if (!_matched) {
              if (part instanceof SystemRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "system requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof ReqDocument) {
                _matched=true;
                this.fileTypeWarning(fileExt, "document", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalConstants) {
                _matched=true;
                this.fileTypeWarning(fileExt, "constants", part);
              }
            }
            if (!_matched) {
              this.fileTypeWarning(fileExt, part.getClass().getName(), part);
            }
          };
          parts.forEach(_function_1);
          break;
        case ReqSpecValidator.REQDOC_FILE_EXT:
          final Consumer<EObject> _function_2 = (EObject part) -> {
            boolean _matched = false;
            if (part instanceof ReqDocument) {
              _matched=true;
              final EList<EObject> reqDocContent = ((ReqDocument)part).getContent();
              final Consumer<EObject> _function_3 = (EObject element) -> {
                boolean _matched_1 = false;
                if (element instanceof Requirement) {
                  _matched_1=true;
                }
                if (!_matched_1) {
                  if (element instanceof Goal) {
                    _matched_1=true;
                    this.fileTypeWarning(fileExt, "goal", element);
                  }
                }
                if (!_matched_1) {
                  if (element instanceof DocumentSection) {
                    _matched_1=true;
                    this.checkRecDocSection(((DocumentSection)element));
                  }
                }
                if (!_matched_1) {
                  this.fileTypeWarning(fileExt, element.getClass().getName(), element);
                }
              };
              reqDocContent.forEach(_function_3);
            }
            if (!_matched) {
              if (part instanceof SystemRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "system requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "global requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalConstants) {
                _matched=true;
                this.fileTypeWarning(fileExt, "constants", part);
              }
            }
            if (!_matched) {
              if (part instanceof StakeholderGoals) {
                _matched=true;
                this.fileTypeWarning(fileExt, "stakeholder goals", part);
              }
            }
            if (!_matched) {
              this.fileTypeWarning(fileExt, part.getClass().getName(), part);
            }
          };
          parts.forEach(_function_2);
          break;
        case ReqSpecValidator.GOALDOC_FILE_EXT:
          final Consumer<EObject> _function_3 = (EObject part) -> {
            boolean _matched = false;
            if (part instanceof ReqDocument) {
              _matched=true;
              final EList<EObject> reqDocContent = ((ReqDocument)part).getContent();
              final Consumer<EObject> _function_4 = (EObject element) -> {
                boolean _matched_1 = false;
                if (element instanceof Goal) {
                  _matched_1=true;
                }
                if (!_matched_1) {
                  if (element instanceof Requirement) {
                    _matched_1=true;
                    this.fileTypeWarning(fileExt, "requirement", element);
                  }
                }
                if (!_matched_1) {
                  if (element instanceof DocumentSection) {
                    _matched_1=true;
                    this.checkGoalDocSection(((DocumentSection)element));
                  }
                }
                if (!_matched_1) {
                  this.fileTypeWarning(fileExt, element.getClass().getName(), element);
                }
              };
              reqDocContent.forEach(_function_4);
            }
            if (!_matched) {
              if (part instanceof SystemRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "system requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "global requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalConstants) {
                _matched=true;
                this.fileTypeWarning(fileExt, "constants", part);
              }
            }
            if (!_matched) {
              if (part instanceof StakeholderGoals) {
                _matched=true;
                this.fileTypeWarning(fileExt, "stakeholder goals", part);
              }
            }
            if (!_matched) {
              this.fileTypeWarning(fileExt, part.getClass().getName(), part);
            }
          };
          parts.forEach(_function_3);
          break;
        case ReqSpecValidator.CONSTANTS_FILE_EXT:
          final Consumer<EObject> _function_4 = (EObject part) -> {
            boolean _matched = false;
            if (part instanceof GlobalConstants) {
              _matched=true;
            }
            if (!_matched) {
              if (part instanceof SystemRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "system requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof GlobalRequirementSet) {
                _matched=true;
                this.fileTypeWarning(fileExt, "global requirements", part);
              }
            }
            if (!_matched) {
              if (part instanceof StakeholderGoals) {
                _matched=true;
                this.fileTypeWarning(fileExt, "stakeholder goals", part);
              }
            }
            if (!_matched) {
              if (part instanceof ReqDocument) {
                _matched=true;
                this.fileTypeWarning(fileExt, "document", part);
              }
            }
            if (!_matched) {
              this.fileTypeWarning(fileExt, part.getClass().getName(), part);
            }
          };
          parts.forEach(_function_4);
          break;
        default:
          break;
      }
    } else {
    }
  }

  public void fileTypeWarning(final String fileType, final String partName, final EObject part) {
    this.warning((((partName + " not allowed in \'") + fileType) + "\' file."), part, null);
  }

  /**
   * TODO: These methods invoke the QuickFixes, not using yet do to unexpected behavior:
   * 		  when removing illegal stakeholder goal from reqspec, the SystemsRequirementSet elements re-order in a way causing an error
   * def void fileTypeError(String fileType, String partName, EObject part, ReqSpec parent){
   * 	error( partName +" not allowed in '"+ fileType + "' file.", part, null, ILLEGAL_OBJECT_FOR_FILETYPE_IN_REQSPEC, partName, EcoreUtil.getURI(parent).toString())
   * }
   * def void fileTypeError(String fileType, String partName, EObject part, ReqDocument parent){
   * 	error( partName +" not allowed in '"+ fileType + "' file.", part, null, ILLEGAL_OBJECT_FOR_FILETYPE_IN_REQDOCUMENT, partName, EcoreUtil.getURI(parent).toString())
   * }
   * def void fileTypeError(String fileType, String partName, EObject part, DocumentSection parent){
   * 	error( partName +" not allowed in '"+ fileType + "' file.", part, null, ILLEGAL_OBJECT_FOR_FILETYPE_IN_DOCUMENTSECTION, partName, EcoreUtil.getURI(parent).toString())
   * }
   */
  public void checkRecDocSection(final DocumentSection section) {
    final EList<EObject> contents = section.getContent();
    final Consumer<EObject> _function = (EObject element) -> {
      boolean _matched = false;
      if (element instanceof Requirement) {
        _matched=true;
      }
      if (!_matched) {
        if (element instanceof Goal) {
          _matched=true;
          this.fileTypeWarning(ReqSpecValidator.REQDOC_FILE_EXT, "goal", element);
        }
      }
      if (!_matched) {
        if (element instanceof DocumentSection) {
          _matched=true;
          this.checkRecDocSection(((DocumentSection)element));
        }
      }
      if (!_matched) {
        this.fileTypeWarning(ReqSpecValidator.REQDOC_FILE_EXT, element.getClass().getName(), element);
      }
    };
    contents.forEach(_function);
  }

  public void checkGoalDocSection(final DocumentSection section) {
    final EList<EObject> contents = section.getContent();
    final Consumer<EObject> _function = (EObject element) -> {
      boolean _matched = false;
      if (element instanceof Goal) {
        _matched=true;
      }
      if (!_matched) {
        if (element instanceof Requirement) {
          _matched=true;
          this.fileTypeWarning(ReqSpecValidator.GOALDOC_FILE_EXT, "requirement", element);
        }
      }
      if (!_matched) {
        if (element instanceof DocumentSection) {
          _matched=true;
          this.checkGoalDocSection(((DocumentSection)element));
        }
      }
      if (!_matched) {
        this.fileTypeWarning(ReqSpecValidator.GOALDOC_FILE_EXT, element.getClass().getName(), element);
      }
    };
    contents.forEach(_function);
  }

  @Check
  public void checkSystemRequirementsUniqueToComponentClassifier(final SystemRequirementSet sysReq) {
    final ComponentClassifier target = sysReq.getTarget();
    final Iterable<SystemRequirementSet> allSystemRequirements = this.reqSpecrefFinder.getSystemRequirementSetsNoExtends(target);
    int _size = IterableExtensions.size(allSystemRequirements);
    boolean _greaterThan = (_size > 1);
    if (_greaterThan) {
      String _name = target.getName();
      String _plus = ("Other System Requirements exist for \'" + _name);
      String _plus_1 = (_plus + 
        "\'. Only one System Requirement is allowed for a specific component.");
      this.error(_plus_1, sysReq, 
        ReqSpecPackage.Literals.SYSTEM_REQUIREMENT_SET__TARGET);
    }
  }

  @Check
  public void checkStakeholderGoalsUniqueToComponentClassifier(final StakeholderGoals shg) {
    final ComponentClassifier target = shg.getTarget();
    final Iterable<StakeholderGoals> allStakeholderGoals = this.reqSpecrefFinder.getStakeholderGoals(target);
    int _size = IterableExtensions.size(allStakeholderGoals);
    boolean _greaterThan = (_size > 1);
    if (_greaterThan) {
      String _name = target.getName();
      String _plus = ("Other Stakeholder Goals exist for \'" + _name);
      String _plus_1 = (_plus + 
        "\'. Only one Stakeholder Goals is allowed for a specific component.");
      this.error(_plus_1, shg, 
        ReqSpecPackage.Literals.STAKEHOLDER_GOALS__TARGET);
    }
  }

  @Check
  public void checkRequirementShadowing(final Requirement req) {
    final String reqName = req.getName().toLowerCase();
    final EList<Requirement> reqEvolvesReferences = req.getEvolvesReference();
    final RequirementSet containingSysReqs = ReqSpecUtilExtension.containingRequirementSet(req);
    if ((containingSysReqs instanceof SystemRequirementSet)) {
      final ComponentClassifier componentClassifier = ((SystemRequirementSet)containingSysReqs).getTarget();
      final ArrayList<ComponentClassifier> classifierParents = new ArrayList<ComponentClassifier>();
      this.buildExtended(componentClassifier, classifierParents);
      final Consumer<ComponentClassifier> _function = (ComponentClassifier classifierParent) -> {
        final Consumer<SystemRequirementSet> _function_1 = (SystemRequirementSet sysreqs) -> {
          final Function1<Requirement, Boolean> _function_2 = (Requirement r) -> {
            return Boolean.valueOf(((Objects.equal(r.getName().toLowerCase(), reqName) && (!r.isDropped())) && (!reqEvolvesReferences.contains(r))));
          };
          boolean _exists = IterableExtensions.<Requirement>exists(sysreqs.getRequirements(), _function_2);
          if (_exists) {
            String _name = req.getName();
            String _plus = ("Requirement \'" + _name);
            String _plus_1 = (_plus + "\' for \'");
            String _name_1 = componentClassifier.getName();
            String _plus_2 = (_plus_1 + _name_1);
            String _plus_3 = (_plus_2 + 
              "\' shadows a requirement of the same name in the System Requirements for \'");
            String _name_2 = classifierParent.getName();
            String _plus_4 = (_plus_3 + _name_2);
            String _plus_5 = (_plus_4 + "\'. Shadowing \'");
            String _plus_6 = (_plus_5 + reqName);
            String _plus_7 = (_plus_6 + 
              "\' must evolve original or original \'");
            String _plus_8 = (_plus_7 + reqName);
            String _plus_9 = (_plus_8 + "\' must be tagged as \'dropped\'");
            this.error(_plus_9, req, 
              ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__NAME);
          }
        };
        this.reqSpecrefFinder.getSystemRequirementSets(classifierParent).forEach(_function_1);
      };
      IterableExtensions.<ComponentClassifier>toList(IterableExtensions.<ComponentClassifier>toSet(classifierParents)).forEach(_function);
    }
  }

  public void buildExtended(final ComponentClassifier compClassifier, final List<ComponentClassifier> ancestors) {
    Classifier ext = compClassifier.getExtended();
    if (((ext != null) && (ext instanceof ComponentClassifier))) {
      ancestors.add(((ComponentClassifier) ext));
      this.buildExtended(((ComponentClassifier) ext), ancestors);
    }
    if ((compClassifier instanceof ComponentImplementation)) {
      ComponentType type = ((ComponentImplementation)compClassifier).getType();
      ancestors.add(type);
      this.buildExtended(type, ancestors);
    }
  }

  @Check
  public void checkRequirementRefinement(final Requirement req) {
    boolean _matched = false;
    boolean _isNullOrEmpty = IterableExtensions.isNullOrEmpty(req.getRefinesReference());
    if (_isNullOrEmpty) {
      _matched=true;
    }
    if (!_matched) {
      RequirementSet _containingRequirementSet = ReqSpecUtilExtension.containingRequirementSet(IterableExtensions.<Requirement>head(req.getRefinesReference()));
      RequirementSet _containingRequirementSet_1 = ReqSpecUtilExtension.containingRequirementSet(req);
      boolean _tripleEquals = (_containingRequirementSet == _containingRequirementSet_1);
      if (_tripleEquals) {
        _matched=true;
      }
    }
    if (!_matched) {
      {
        final ArrayList<ComponentClassifier> classifierParents = new ArrayList<ComponentClassifier>();
        final RequirementSet reqs = ReqSpecUtilExtension.containingRequirementSet(req);
        if ((reqs instanceof SystemRequirementSet)) {
          this.buildExtended(((SystemRequirementSet)reqs).getTarget(), classifierParents);
          final RequirementSet refinedreqs = ReqSpecUtilExtension.containingRequirementSet(IterableExtensions.<Requirement>head(req.getRefinesReference()));
          if ((refinedreqs instanceof SystemRequirementSet)) {
            boolean _contains = classifierParents.contains(((SystemRequirementSet)refinedreqs).getTarget());
            if (_contains) {
              return;
            }
            String _name = req.getName();
            String _plus = ("Requirement \'" + _name);
            String _plus_1 = (_plus + "\' refined from \'");
            String _name_1 = IterableExtensions.<Requirement>head(req.getRefinesReference()).getName();
            String _plus_2 = (_plus_1 + _name_1);
            String _plus_3 = (_plus_2 + 
              "\' and must either be in the same System Requirements or \'");
            String _name_2 = req.getName();
            String _plus_4 = (_plus_3 + _name_2);
            String _plus_5 = (_plus_4 + 
              "\' must be for an extension or implementation of the component \'");
            String _name_3 = IterableExtensions.<Requirement>head(req.getRefinesReference()).getName();
            String _plus_6 = (_plus_5 + _name_3);
            String _plus_7 = (_plus_6 + "\' is for. \'");
            this.error(_plus_7, req, 
              ReqSpecPackage.Literals.CONTRACTUAL_ELEMENT__NAME);
          }
        }
      }
    }
  }

  @Check
  public void checkIncludeGlobalRequirement(final IncludeGlobalRequirement igr) {
    boolean _not = (!((igr.getInclude() instanceof GlobalRequirementSet) || (igr.getInclude() instanceof Requirement)));
    if (_not) {
      this.error("Must include global requirements or requirement in global requirements.", igr, 
        ReqSpecPackage.Literals.INCLUDE_GLOBAL_REQUIREMENT__INCLUDE, ReqSpecValidator.INCORRECT_GLOBAL_REQUIREMENT_INCLUDE);
    }
  }

  @Check
  public void checkWhenCondition(final WhenCondition wc) {
    Method _javaMethod = ExecuteJavaUtil.getJavaMethod(wc.getCondition());
    boolean _tripleEquals = (_javaMethod == null);
    if (_tripleEquals) {
      String _condition = wc.getCondition();
      String _plus = ("Could not find Java method " + _condition);
      String _plus_1 = (_plus + " with single EObject parameter");
      this.error(_plus_1, 
        ReqSpecPackage.Literals.WHEN_CONDITION__CONDITION, ReqSpecValidator.CONDITION_METHOD_NOT_FOUND);
    }
  }
}