Aadl2QuickfixProvider.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.xtext.aadl2.ui.quickfix;

import com.google.inject.Inject;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.IURIEditorOpener;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.editor.model.edit.IModification;
import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
import org.eclipse.xtext.ui.editor.model.edit.ISemanticModification;
import org.eclipse.xtext.ui.editor.quickfix.Fix;
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.osate.aadl2.AbstractFeature;
import org.osate.aadl2.Access;
import org.osate.aadl2.AccessType;
import org.osate.aadl2.ArrayDimension;
import org.osate.aadl2.ArraySize;
import org.osate.aadl2.ComponentPrototype;
import org.osate.aadl2.Connection;
import org.osate.aadl2.DirectedFeature;
import org.osate.aadl2.EnumerationLiteral;
import org.osate.aadl2.EnumerationType;
import org.osate.aadl2.Feature;
import org.osate.aadl2.FeatureGroup;
import org.osate.aadl2.FeatureGroupType;
import org.osate.aadl2.FeaturePrototype;
import org.osate.aadl2.FeaturePrototypeActual;
import org.osate.aadl2.FeaturePrototypeBinding;
import org.osate.aadl2.FeaturePrototypeReference;
import org.osate.aadl2.GroupExtension;
import org.osate.aadl2.ModalElement;
import org.osate.aadl2.ModalPath;
import org.osate.aadl2.ModalPropertyValue;
import org.osate.aadl2.Mode;
import org.osate.aadl2.ModeBinding;
import org.osate.aadl2.ModelUnit;
import org.osate.aadl2.NamedElement;
import org.osate.aadl2.NumericRange;
import org.osate.aadl2.PackageSection;
import org.osate.aadl2.PortSpecification;
import org.osate.aadl2.PropertyExpression;
import org.osate.aadl2.PropertySet;
import org.osate.aadl2.Prototype;
import org.osate.aadl2.Subcomponent;
import org.osate.aadl2.UnitLiteral;
import org.osate.xtext.aadl2.properties.ui.quickfix.PropertiesQuickfixProvider;
import org.osate.xtext.aadl2.validation.Aadl2Validator;

@SuppressWarnings("all")
public class Aadl2QuickfixProvider extends PropertiesQuickfixProvider {
  @Inject
  private IURIEditorOpener editorOpener;

  /**
   * QuickFix for matching the defining and ending identifiers of classifiers, packages, and property sets.
   * The issue data array is expected to have three elements:
   * 
   * issue.getData()[0]: The defining identifier of the classifier or model unit.
   * issue.getData()[1]: The ending identifier of the classifier or model unit.
   * issue.getData()[2]: The offset of the ending identifier within the Xtext document.
   */
  @Fix(Aadl2Validator.MISMATCHED_BEGINNING_AND_ENDING_IDENTIFIERS)
  public void fixMismatchedBeginningAndEndingIdentifiers(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String beginningName = issue.getData()[0];
    final String endingName = issue.getData()[1];
    final int endingIdentifierOffset = Integer.parseInt(issue.getData()[2]);
    acceptor.accept(issue, (("Change defining identifier to \'" + endingName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          ((NamedElement) element).setName(endingName);
        }
      });
    acceptor.accept(issue, (("Change ending identifier to \'" + beginningName) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(endingIdentifierOffset, endingName.length(), beginningName);
      }
    });
  }

  /**
   * QuickFix for Non-unique ComponentType names, most likely "refined to" missing.
   * The issue data array is expected to have three elements:
   * 
   * issue.getData()[0]: The name of the element.
   * issue.getData()[1]: The offset of the ":".
   * issue.getData()[2]: replacement value.
   */
  @Fix(Aadl2Validator.DUPLICATE_COMPONENT_TYPE_NAME)
  public void fixDuplicateComponentType(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String componentTypeName = issue.getData()[0];
    final int offset = Integer.parseInt(issue.getData()[1]);
    final String replacementVal = issue.getData()[2];
    acceptor.accept(issue, (("Add \'refined to\' to \'" + componentTypeName) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(offset, 1, replacementVal);
      }
    });
  }

  /**
   * QuickFix for duplicate literal in an enumeration
   * issue.getData()[0]: The name of the EnumerationLiteral.
   */
  @Fix(Aadl2Validator.DUPLICATE_LITERAL_IN_ENUMERATION)
  public void fixDuplicateLiteralInEnumeration(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String dupeLiteralName = issue.getData()[0];
    acceptor.accept(issue, (("Remove duplicate literal \'" + dupeLiteralName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final EnumerationLiteral el = ((EnumerationLiteral) element);
          EObject _eContainer = el.eContainer();
          final EnumerationType enumContainer = ((EnumerationType) _eContainer);
          enumContainer.getOwnedLiterals().remove(el);
        }
      });
  }

  /**
   * QuickFix for unit literal being out of sequence
   * issue.getData(0) UnitLiteral.baseUnit.name
   * issue.getData(1) ... issue.getData(n): Alternating strings of the UnitLiteral names and URI.
   */
  @Fix(Aadl2Validator.UNIT_LITERAL_OUT_OF_ORDER)
  public void fixUnitLiteralOutOfOrder(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String baseUnitName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final Iterator<String> iter = ((List<String>)Conversions.doWrapArray(issue.getData())).iterator();
    boolean _hasNext = iter.hasNext();
    if (_hasNext) {
      iter.next();
    }
    while (iter.hasNext()) {
      {
        final String ulName = iter.next();
        final String nextUri = iter.next();
        acceptor.accept(issue, (((("Change unit base type \'" + baseUnitName) + "\' to \'") + ulName) + "\'"), null, null, 
          new ISemanticModification() {
            @Override
            public void apply(final EObject element, final IModificationContext context) throws Exception {
              final ResourceSet resourceSet = element.eResource().getResourceSet();
              EObject _eObject = resourceSet.getEObject(URI.createURI(nextUri), true);
              final UnitLiteral newBaseUnit = ((UnitLiteral) _eObject);
              ((UnitLiteral) element).setBaseUnit(newBaseUnit);
            }
          });
      }
    }
  }

  /**
   * QuickFix for mode in modal property value not being defined for the container
   * issue.getData(0) mode.name
   * issue.getData(1) undefinedMode URI
   * issue.getData(2) containerName
   * issue.getData(3) containerURI
   * issue.getData(4) ModalPropertyValue
   * issue.getData(5) ... issue.getData(n): Alternating strings of proposed replacement mode names and URI.
   */
  @Fix(Aadl2Validator.MODE_NOT_DEFINED_IN_CONTAINER)
  public void fixModeNotDefinedInContainer(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String modeName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String undefinedModeURI = issue.getData()[1];
    final String containerName = issue.getData()[2];
    final String containerURI = issue.getData()[3];
    final String modalPropertyValueURI = issue.getData()[4];
    acceptor.accept(issue, (((("Add \'" + modeName) + "\' to in modes of \'") + containerName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final ResourceSet resourceSet = element.eResource().getResourceSet();
          EObject _eObject = resourceSet.getEObject(URI.createURI(containerURI), true);
          final ModalElement container = ((ModalElement) _eObject);
          EObject _eObject_1 = resourceSet.getEObject(URI.createURI(undefinedModeURI), true);
          final Mode undefinedMode = ((Mode) _eObject_1);
          boolean _matched = false;
          if (container instanceof ModalPath) {
            _matched=true;
            ((ModalPath)container).getInModeOrTransitions().add(undefinedMode);
          }
          if (!_matched) {
            container.getInModes().add(undefinedMode);
          }
        }
      });
    final Iterator<String> iter = ((List<String>)Conversions.doWrapArray(issue.getData())).iterator();
    for (int i = 0; (i < 5); i++) {
      boolean _hasNext = iter.hasNext();
      if (_hasNext) {
        iter.next();
      }
    }
    while (iter.hasNext()) {
      {
        final String replacementName = iter.next();
        final String nextUri = iter.next();
        acceptor.accept(issue, (((("Replace \'" + modeName) + "\' with \'") + replacementName) + "\'"), null, null, 
          new ISemanticModification() {
            @Override
            public void apply(final EObject element, final IModificationContext context) throws Exception {
              final ResourceSet resourceSet = element.eResource().getResourceSet();
              EObject _eObject = resourceSet.getEObject(URI.createURI(nextUri), true);
              final Mode replacementMode = ((Mode) _eObject);
              EObject _eObject_1 = resourceSet.getEObject(URI.createURI(undefinedModeURI), true);
              final Mode undefinedMode = ((Mode) _eObject_1);
              EObject _eObject_2 = resourceSet.getEObject(URI.createURI(modalPropertyValueURI), true);
              final ModalPropertyValue mpv = ((ModalPropertyValue) _eObject_2);
              mpv.getInModes().remove(undefinedMode);
              mpv.getInModes().add(replacementMode);
            }
          });
      }
    }
  }

  /**
   * QuickFix for using self keyword when not allowed
   * issue.getData(0) offSet
   * issue.getData(1) connectionEndURI
   */
  @Fix(Aadl2Validator.SELF_NOT_ALLOWED)
  public void fixSelfNotAllowed(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final int offSet = Integer.parseInt(IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData()))));
    final String alternateConnectionEndType = issue.getData()[1];
    acceptor.accept(issue, "Remove \'self\'", null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(offSet, 5, "");
      }
    });
    boolean _equals = alternateConnectionEndType.equals("processor");
    if (_equals) {
      acceptor.accept(issue, "Replace \'self\' with \'processor\'", null, null, new IModification() {
        @Override
        public void apply(final IModificationContext context) throws Exception {
          context.getXtextDocument().replace(offSet, 4, "processor");
        }
      });
    }
  }

  /**
   * QuickFix for using processor keyword when not allowed
   * issue.getData(0) offSet
   * issue.getData(1) connectionEndURI
   */
  @Fix(Aadl2Validator.PROCESSOR_NOT_ALLOWED)
  public void fixProcessorNotAllowed(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final int offSet = Integer.parseInt(IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData()))));
    final String alternateConnectionEndType = issue.getData()[1];
    acceptor.accept(issue, "Remove \'processor\'", null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(offSet, 10, "");
      }
    });
    boolean _equals = alternateConnectionEndType.equals("self");
    if (_equals) {
      acceptor.accept(issue, "Replace \'processor\' with \'self\'", null, null, new IModification() {
        @Override
        public void apply(final IModificationContext context) throws Exception {
          context.getXtextDocument().replace(offSet, 9, "self");
        }
      });
    }
  }

  /**
   * QuickFix for flow impl kind not matching flow spec kind
   * issue.getData(0) impl kind name
   * issue.getData(1) flow spec name
   * issue,getData(2) offSet
   */
  @Fix(Aadl2Validator.INCONSISTENT_FLOW_KIND)
  public void fixInconsistentFlowKind(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String flowImplKindName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String flowSpecKindName = issue.getData()[1];
    final int offSet = Integer.parseInt(issue.getData()[2]);
    acceptor.accept(issue, (((("Change \'" + flowImplKindName) + "\' to \'") + flowSpecKindName) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(offSet, flowImplKindName.length(), flowSpecKindName);
      }
    });
  }

  /**
   * QuickFix for out flow feature identifier not matching the flow specification
   * issue.getData(0) outImplName
   * issue.getData(1) specName
   * issue,getData(2) featureOffSet
   * issue,getData(3) contextOffset
   */
  @Fix(Aadl2Validator.OUT_FLOW_FEATURE_IDENTIFIER_NOT_SPEC)
  public void fixOutFlowIdentifierNotSpec(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String outImplName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String specName = issue.getData()[1];
    final int featureOffSet = Integer.parseInt(issue.getData()[2]);
    final int contextOffset = Integer.parseInt(issue.getData()[3]);
    acceptor.accept(issue, (((("Change \'" + outImplName) + "\' to \'") + specName) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        int useOffSet = featureOffSet;
        String replacement = specName;
        if ((0 < contextOffset)) {
          useOffSet = contextOffset;
        }
        context.getXtextDocument().replace(useOffSet, outImplName.length(), replacement);
      }
    });
  }

  /**
   * QuickFix for in flow feature identifier not matching the flow specification
   * issue.getData(0) inImplName
   * issue.getData(1) specName
   * issue,getData(2) featureOffSet
   * issue,getData(3) contextOffset
   */
  @Fix(Aadl2Validator.IN_FLOW_FEATURE_IDENTIFIER_NOT_SPEC)
  public void fixInFlowIdentifierNotSpec(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String inImplName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String specName = issue.getData()[1];
    final int featureOffSet = Integer.parseInt(issue.getData()[2]);
    acceptor.accept(issue, (((("Change \'" + inImplName) + "\' to \'") + specName) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        int useOffSet = featureOffSet;
        String replacement = specName;
        context.getXtextDocument().replace(useOffSet, inImplName.length(), replacement);
      }
    });
  }

  /**
   * QuickFix for Subcomponent not in flow modes
   * issue.getData(0) flowModeName
   * issue.getData(1) flowModeURI
   * issue,getData(2) subcomponentName
   * issue,getData(3) subcomponentURI
   */
  @Fix(Aadl2Validator.SUBCOMPONENT_NOT_IN_FLOW_MODE)
  public void fixSubcomponentNotInFlowMode(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String flowModeName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String flowModeURI = issue.getData()[1];
    final String subcomponentName = issue.getData()[2];
    final String subcomponentURI = issue.getData()[3];
    acceptor.accept(issue, (((("Add mode \'" + flowModeName) + "\' to in modes of \'") + subcomponentName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final URI suburi = URI.createURI(subcomponentURI);
          final IXtextDocument doc = context.getXtextDocument(suburi);
          doc.<Object>modify(new IUnitOfWork.Void<XtextResource>() {
            @Override
            public void process(final XtextResource state) throws Exception {
              EObject _eObject = state.getResourceSet().getEObject(URI.createURI(flowModeURI), true);
              final Mode flowMode = ((Mode) _eObject);
              EObject _eObject_1 = state.getResourceSet().getEObject(suburi, true);
              final Subcomponent subcomponent = ((Subcomponent) _eObject_1);
              final ModeBinding modeBinding = subcomponent.createOwnedModeBinding();
              modeBinding.setParentMode(flowMode);
            }
          });
          Aadl2QuickfixProvider.this.editorOpener.open(suburi, true);
        }
      });
  }

  /**
   * QuickFix for Subcomponent not in flow modes
   * issue.getData(0) flowModeName
   * issue.getData(1) flowModeURI
   * issue,getData(2) connectionName
   * issue,getData(3) connectionURI
   */
  @Fix(Aadl2Validator.CONNECTION_NOT_IN_FLOW_MODE)
  public void fixConnectionNotInFlowMode(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String flowModeName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String flowModeURI = issue.getData()[1];
    final String connectionName = issue.getData()[2];
    final String connectionURI = issue.getData()[3];
    acceptor.accept(issue, (((("Add mode \'" + flowModeName) + "\' to in modes of \'") + connectionName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final URI connuri = URI.createURI(connectionURI);
          final IXtextDocument doc = context.getXtextDocument(connuri);
          doc.<Object>modify(new IUnitOfWork.Void<XtextResource>() {
            @Override
            public void process(final XtextResource state) throws Exception {
              EObject _eObject = state.getResourceSet().getEObject(URI.createURI(flowModeURI), true);
              final Mode flowMode = ((Mode) _eObject);
              EObject _eObject_1 = state.getResourceSet().getEObject(connuri, true);
              final Connection connection = ((Connection) _eObject_1);
              connection.getInModeOrTransitions().add(flowMode);
            }
          });
          Aadl2QuickfixProvider.this.editorOpener.open(connuri, true);
        }
      });
  }

  /**
   * QuickFix for Subcomponent not in flow modes
   * issue.getData(0) targetName
   * issue.getData(1) targetURI
   * issue,getData(2) neededModeName
   * issue,getData(3) neededModeURI
   */
  @Fix(Aadl2Validator.END_TO_END_FLOW_SEGMENT_NOT_IN_MODE)
  public void fixEndToEndFlowSegmentNotInMode(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String targetName = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String targetURI = issue.getData()[1];
    final String neededModeName = issue.getData()[2];
    final String neededModeURI = issue.getData()[3];
    acceptor.accept(issue, (((("Add mode \'" + neededModeName) + "\' to in modes of \'") + targetName) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final URI targeturi = URI.createURI(targetURI);
          final IXtextDocument doc = context.getXtextDocument(targeturi);
          doc.<Object>modify(new IUnitOfWork.Void<XtextResource>() {
            @Override
            public void process(final XtextResource state) throws Exception {
              EObject _eObject = state.getResourceSet().getEObject(URI.createURI(neededModeURI), true);
              final Mode neededMode = ((Mode) _eObject);
              final EObject targetObject = state.getResourceSet().getEObject(targeturi, true);
              boolean _matched = false;
              if (targetObject instanceof Subcomponent) {
                _matched=true;
                final ModeBinding modeBinding = ((Subcomponent)targetObject).createOwnedModeBinding();
                modeBinding.setParentMode(neededMode);
              }
              if (!_matched) {
                if (targetObject instanceof ModalPath) {
                  _matched=true;
                  ((ModalPath)targetObject).getInModeOrTransitions().add(neededMode);
                }
              }
            }
          });
          Aadl2QuickfixProvider.this.editorOpener.open(targeturi, true);
        }
      });
  }

  /**
   * QuickFix for generic text replacement
   * issue.getData(0) changeFrom
   * issue.getData(1) changeTo
   * issue,getData(2) offSet
   */
  @Fix(Aadl2Validator.GENERIC_TEXT_REPLACEMENT)
  public void fixByGenericTextReplacement(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    final int offSet = Integer.parseInt(issue.getData()[2]);
    acceptor.accept(issue, (((("Change \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        context.getXtextDocument().replace(offSet, changeFrom.length(), changeTo);
      }
    });
  }

  /**
   * QuickFix for Array size not same as reference list size
   * issue.getData(0) arraySize
   * issue.getData(1) referenceListSize
   */
  @Fix(Aadl2Validator.ARRAY_SIZE_NOT_EQUAL_REFERENCE_LIST_SIZE)
  public void fixArraySizeNotEqualRefernceListSize(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final int arraySize = Integer.parseInt(IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData()))));
    final int referenceListSize = Integer.parseInt(issue.getData()[1]);
    acceptor.accept(issue, (((("Change Array size from \'" + Integer.valueOf(arraySize)) + "\' to \'") + Integer.valueOf(referenceListSize)) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final Subcomponent subcomponent = ((Subcomponent) element);
          ArraySize _size = IterableExtensions.<ArrayDimension>head(subcomponent.getArrayDimensions()).getSize();
          _size.setSize(referenceListSize);
        }
      });
  }

  /**
   * QuickFix for Prototype must be an array because the refined prototype is an array
   */
  @Fix(Aadl2Validator.PROTOTYPE_NOT_ARRAY)
  public void fixPrototypeMusBeAnArray(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Change prototype to an array", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final ComponentPrototype prototype = ((ComponentPrototype) element);
          prototype.setArray(true);
        }
      });
  }

  /**
   * QuickFix for Prototype binding direction not consistent with formal
   * issue.getData(0) = actualDirection.toString();
   * issue.getData(1) = formalDirection.toString();
   */
  @Fix(Aadl2Validator.PROTOTYPE_BINDING_DIRECTION_NOT_CONSISTENT_WITH_FORMAL)
  public void fixPrototypeBindingDirection(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    acceptor.accept(issue, (((("Change \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final FeaturePrototypeBinding binding = ((FeaturePrototypeBinding) element);
          Prototype _formal = binding.getFormal();
          final FeaturePrototype formal = ((FeaturePrototype) _formal);
          final FeaturePrototypeActual actual = binding.getActual();
          boolean _matched = false;
          if (actual instanceof FeaturePrototypeReference) {
            _matched=true;
            ((FeaturePrototypeReference)actual).setIn(formal.isIn());
            ((FeaturePrototypeReference)actual).setOut(formal.isOut());
          }
          if (!_matched) {
            if (actual instanceof PortSpecification) {
              _matched=true;
              ((PortSpecification)actual).setIn(formal.isIn());
              ((PortSpecification)actual).setOut(formal.isOut());
            }
          }
        }
      });
  }

  /**
   * QuickFix for incompatible direction for prototype refinement
   * issue.getData(0) = changeFrom
   * issue.getData(1) = changeTo;
   */
  @Fix(Aadl2Validator.INCOMPATIBLE_DIRECTION_FOR_PROTOTYPE_REFINEMENT)
  public void fixIncompatibleDirectionForPrototypeRefinement(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    acceptor.accept(issue, (((("Change \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final FeaturePrototype prototype = ((FeaturePrototype) element);
          Prototype _refined = prototype.getRefined();
          final FeaturePrototype refined = ((FeaturePrototype) _refined);
          prototype.setIn(refined.isIn());
          prototype.setOut(refined.isOut());
        }
      });
  }

  /**
   * QuickFix for incompatible  feature direction in refinement
   * issue.getData(0) = changeFrom
   * issue.getData(1) = changeTo;
   */
  @Fix(Aadl2Validator.INCOMPATIBLE_FEATURE_DIRECTION_IN_REFINEMENT)
  public void fixIncompatibleFeatureDirectionInRefinement(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    acceptor.accept(issue, (((("Change \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final DirectedFeature feature = ((DirectedFeature) element);
          Feature _refined = feature.getRefined();
          final DirectedFeature refined = ((DirectedFeature) _refined);
          feature.setIn(refined.isIn());
          feature.setOut(refined.isOut());
        }
      });
  }

  /**
   * QuickFix for incompatible  feature direction in refinement
   * issue.getData(0) = changeFrom
   * issue.getData(1) = changeTo;
   */
  @Fix(Aadl2Validator.ABSTRACT_FEATURE_DIRECTION_DOES_NOT_MATCH_PROTOTYPE)
  public void fixAbstractFeatureDirectionDoesNotMatchPrototype(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    acceptor.accept(issue, (((("Change \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final AbstractFeature feature = ((AbstractFeature) element);
          final FeaturePrototype prototype = feature.getFeaturePrototype();
          feature.setIn(prototype.isIn());
          feature.setOut(prototype.isOut());
        }
      });
  }

  /**
   * QuickFix for incompatible feature direction in refinement
   * issue.getData(0) = changeFrom
   */
  @Fix(Aadl2Validator.ABSTRACT_FEATURE_DIRECTION_NOT_IN_PROTOTYPE)
  public void fixAbstractFeatureDirectionNotInPrototype(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    acceptor.accept(issue, (("Remove \'" + changeFrom) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final AbstractFeature feature = ((AbstractFeature) element);
          feature.setIn(false);
          feature.setOut(false);
        }
      });
  }

  /**
   * QuickFix for added direction in abstract feature refinement
   * issue.getData(0) = changeFrom
   */
  @Fix(Aadl2Validator.ADDED_DIRECTION_IN_ABSTRACT_FEATURE_REFINEMENT)
  public void fixAddedDirectionInAbstractFeatureRefinement(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    acceptor.accept(issue, (("Remove \'" + changeFrom) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final AbstractFeature feature = ((AbstractFeature) element);
          feature.setIn(false);
          feature.setOut(false);
        }
      });
  }

  /**
   * QuickFix for added prototype or classifier in abstract feature refinement
   * issue.getData(0) = changeFrom
   */
  @Fix(Aadl2Validator.ADDED_PROTOTYPE_OR_CLASSIFIER_IN_ABSTRACT_FEATURE_REFINEMENT)
  public void fixAddedPrototypeOrClassifierInAbstractFeatureRefinement(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    acceptor.accept(issue, (("Remove \'" + changeFrom) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final AbstractFeature feature = ((AbstractFeature) element);
          feature.setFeaturePrototype(null);
        }
      });
  }

  /**
   * QuickFix for chained inverse feature group types
   */
  @Fix(Aadl2Validator.CHAINED_INVERSE_FEATURE_GROUP_TYPES)
  public void fixChainedInverseFeatureGroupTypes(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Remove inverse", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final FeatureGroupType featureGroupType = ((FeatureGroupType) element);
          featureGroupType.setInverse(null);
        }
      });
  }

  /**
   * QuickFix for extending inverse feature group types
   */
  @Fix(Aadl2Validator.EXTENDED_INVERSE_FEATURE_GROUP_TYPE)
  public void fixExtendedInverseFeatureGroupTypes(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Remove extends", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final GroupExtension groupExtension = ((GroupExtension) element);
          EObject _eContainer = groupExtension.eContainer();
          final FeatureGroupType featureGroup = ((FeatureGroupType) _eContainer);
          featureGroup.setOwnedExtension(null);
        }
      });
  }

  /**
   * QuickFix for extending inverse feature group types
   */
  @Fix(Aadl2Validator.INVERSE_IN_FEATURE_GROUP_TYPE_EXTENSION)
  public void fixInverseInFeatureGroupTypeExtension(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Remove extends", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final GroupExtension groupExtension = ((GroupExtension) element);
          EObject _eContainer = groupExtension.eContainer();
          final FeatureGroupType featureGroup = ((FeatureGroupType) _eContainer);
          featureGroup.setOwnedExtension(null);
        }
      });
    acceptor.accept(issue, "Remove inverse", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final GroupExtension groupExtension = ((GroupExtension) element);
          EObject _eContainer = groupExtension.eContainer();
          final FeatureGroupType featureGroup = ((FeatureGroupType) _eContainer);
          featureGroup.setInverse(null);
        }
      });
  }

  /**
   * QuickFix for inverse in feature group
   */
  @Fix(Aadl2Validator.INVERSE_IN_FEATURE_GROUP)
  public void fixInverseInFeatureGroup(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Remove inverse", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final FeatureGroup featureGroup = ((FeatureGroup) element);
          featureGroup.setInverse(false);
        }
      });
  }

  /**
   * QuickFix for extending inverse feature group types
   * issue.getData(0) = valid direction if any or empty String
   * issue.getData(1) = current direction
   */
  @Fix(Aadl2Validator.DIRECTION_NOT_SAME_AS_FEATURE_GROUP_MEMBERS)
  public void fixDirectionNotTheSameAsFeatureGroupMembers(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String validDirection = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String currentDirection = issue.getData()[1];
    acceptor.accept(issue, (("Remove \'" + currentDirection) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final FeatureGroup featureGroup = ((FeatureGroup) element);
          featureGroup.setIn(false);
          featureGroup.setOut(false);
        }
      });
    boolean _equals = validDirection.equals("");
    boolean _not = (!_equals);
    if (_not) {
      acceptor.accept(issue, (((("Change direction from \'" + currentDirection) + "\' to \'") + validDirection) + "\'"), null, null, 
        new ISemanticModification() {
          @Override
          public void apply(final EObject element, final IModificationContext context) throws Exception {
            final FeatureGroup featureGroup = ((FeatureGroup) element);
            if (validDirection != null) {
              switch (validDirection) {
                case "in":
                  featureGroup.setIn(true);
                  featureGroup.setOut(false);
                  break;
                case "out":
                  featureGroup.setIn(false);
                  featureGroup.setOut(true);
                  break;
                default:
                  {
                    featureGroup.setIn(false);
                    featureGroup.setOut(false);
                  }
                  break;
              }
            } else {
              {
                featureGroup.setIn(false);
                featureGroup.setOut(false);
              }
            }
          }
        });
    }
  }

  /**
   * QuickFix for reverse access kind
   * issue.getData.get(0) changeFrom
   * issue.getData.get(1) changeTo
   */
  @Fix(Aadl2Validator.REVERSE_ACCESS_KIND)
  public void fixReverseAccessKind(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String changeFrom = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String changeTo = issue.getData()[1];
    acceptor.accept(issue, (((("Change access from \'" + changeFrom) + "\' to \'") + changeTo) + "\'"), null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final Access access = ((Access) element);
          access.setKind(AccessType.getByName(changeTo));
        }
      });
  }

  /**
   * QuickFix for swapping Upper and Lower bounds in a range value when the upper is less than the lower
   * issue.getData.get(0) lowerURI
   * issue.getData.get(1) upperURI
   * issue.getData.get(2) keyword before the range
   * issue.getData.get(3) offSet of keyword before the range
   */
  @Fix(Aadl2Validator.NUMERIC_RANGE_UPPER_LESS_THAN_LOWER)
  public void fixNumericRangeUpperLessThanLower(final Issue issue, final IssueResolutionAcceptor acceptor) {
    final String lowerURI = IterableExtensions.<String>head(((Iterable<String>)Conversions.doWrapArray(issue.getData())));
    final String upperURI = issue.getData()[1];
    final String changeFrom = issue.getData()[2];
    final int offSet = Integer.parseInt(issue.getData()[3]);
    final String changeTo = (changeFrom + " ");
    acceptor.accept(issue, "Switch upper and lower bounds of the range", null, null, new IModification() {
      @Override
      public void apply(final IModificationContext context) throws Exception {
        IXtextDocument _xtextDocument = context.getXtextDocument();
        _xtextDocument.<Object>modify(new IUnitOfWork.Void<XtextResource>() {
          @Override
          public void process(final XtextResource state) throws Exception {
            final ResourceSet resourceSet = state.getResourceSet();
            final EObject element = resourceSet.getEObject(issue.getUriToProblem(), true);
            EObject _eObject = resourceSet.getEObject(URI.createURI(lowerURI), true);
            final PropertyExpression oldLower = ((PropertyExpression) _eObject);
            EObject _eObject_1 = resourceSet.getEObject(URI.createURI(upperURI), true);
            final PropertyExpression oldUpper = ((PropertyExpression) _eObject_1);
            ((NumericRange) element).setUpperBound(oldLower);
            ((NumericRange) element).setLowerBound(oldUpper);
          }
        });
        context.getXtextDocument().replace(offSet, changeFrom.length(), changeTo);
      }
    });
  }

  /**
   * QuickFix by making a connection bidirectional
   */
  @Fix(Aadl2Validator.MAKE_CONNECTION_BIDIRECTIONAL)
  public void fixMakeConnectionBiderctional(final Issue issue, final IssueResolutionAcceptor acceptor) {
    acceptor.accept(issue, "Make connection bidirectional", null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final Connection connection = ((Connection) element);
          connection.setBidirectional(true);
        }
      });
  }

  /**
   * QuickFix for adding a removing unused propertySet in packageSection with clause
   * The issue data array is expected to have two elements:
   * 
   * issue.getData()[0]: The name of the package or property set
   * issue.getData()[1]: The URI String of the referenced AadlPackage or PropertySet.
   */
  @Fix(Aadl2Validator.WITH_NOT_USED)
  public void fixWithNotUsed(final Issue issue, final IssueResolutionAcceptor acceptor) {
    String _get = issue.getData()[0];
    String _plus = ("Remove \'" + _get);
    String _plus_1 = (_plus + "\' from the with clause");
    acceptor.accept(issue, _plus_1, null, null, 
      new ISemanticModification() {
        @Override
        public void apply(final EObject element, final IModificationContext context) throws Exception {
          final ResourceSet resourceSet = element.eResource().getResourceSet();
          EObject _eObject = resourceSet.getEObject(URI.createURI(issue.getData()[1]), true);
          final ModelUnit importedModelUnit = ((ModelUnit) _eObject);
          boolean _matched = false;
          if (element instanceof PackageSection) {
            _matched=true;
            ((PackageSection)element).getImportedUnits().remove(importedModelUnit);
          }
          if (!_matched) {
            if (element instanceof PropertySet) {
              _matched=true;
              ((PropertySet)element).getImportedUnits().remove(importedModelUnit);
            }
          }
        }
      });
  }
}