<%if (isImplementation && genFeature.isListType()) {%>
  <%if (!UML2GenModelUtil.getSubsetGenFeatures(genClass, genFeature, UML2GenModelUtil.isDerivedUnionListType(genClass, genFeature)).isEmpty()) {%>
	/**
	 * The array of subset feature identifiers for the '{@link #<%=genFeature.getGetAccessor()%>() <em><%=genFeature.getFormattedName()%></em>}' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 * @ordered
	 */
	protected static final int[] <%=genFeature.getUpperName()%>_ESUBSETS = <%=UML2GenModelUtil.getSubsetFeatureIDArray(genClass, genFeature, UML2GenModelUtil.isDerivedUnionListType(genClass, genFeature))%>;

  <%}%>
  <%if (!UML2GenModelUtil.getSupersetGenFeatures(genClass, genFeature, false).isEmpty()) {%>
	/**
	 * The array of superset feature identifiers for the '{@link #<%=genFeature.getGetAccessor()%>() <em><%=genFeature.getFormattedName()%></em>}' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 * @ordered
	 */
	protected static final int[] <%=genFeature.getUpperName()%>_ESUPERSETS = <%=UML2GenModelUtil.getSupersetFeatureIDArray(genClass, genFeature)%>;

  <%}%>
<%}%>
<%if (!genClass.getExtendedGenFeatures().contains(genFeature) && UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) { List keyGenFeatures = UML2GenModelUtil.getKeyGenFeatures(genFeature);%>
  <%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>
    <%if (isInterface) {%>
	/**
      <%if (!keyGenFeatures.isEmpty()) {%>
        <%if (genFeature.isListType()) {%>
	 * Creates a new {@link <%=genFeature.getQualifiedListItemType()%>}, with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, and appends it to the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%} else {%>
	 * Creates a new {@link <%=genFeature.getType()%>}, with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, and sets the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%}%>
      <%} else {%>
        <%if (genFeature.isListType()) {%>
	 * Creates a new {@link <%=genFeature.getQualifiedListItemType()%>} and appends it to the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%} else {%>
	 * Creates a new {@link <%=genFeature.getType()%>} and sets the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%}%>
      <%}%>
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
      <%for (int index = 0, size = keyGenFeatures.size(); index < size; index++) {%>
	 * @param <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> The <%=UML2GenModelUtil.getFormattedKeyFeatureName(genFeature, index)%> for the new {@link <%=genFeature.getQualifiedListItemType()%>}, or <code>null</code>.
      <%}%>
	 * @param eClass The Ecore class of the {@link <%=genFeature.getQualifiedListItemType()%>} to create.
	 * @return The new {@link <%=genFeature.getQualifiedListItemType()%>}.
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 */
    <%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%}%>
    <%if (!isImplementation) {%>
	<%=genFeature.getListItemType()%> create<%=genFeature.getCapName()%>(<%if (!keyGenFeatures.isEmpty()) {%><%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>, <%}%><%=genModel.getImportedName("org.eclipse.emf.ecore.EClass")%> eClass);

    <%} else { int index = 0;%>
      <%if (genModel.useClassOverrideAnnotation() && UML2GenModelUtil.isDuplicate(genFeature) && !UML2GenModelUtil.isRedefinition(genFeature)) {%>
	@Override
      <%}%>
	public <%=genFeature.getListItemType()%> create<%=genFeature.getCapName()%>(<%if (!keyGenFeatures.isEmpty()) {%><%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>, <%}%><%=genModel.getImportedName("org.eclipse.emf.ecore.EClass")%> eClass)
	{
		<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%> new<%=genFeature.getCapName()%> = (<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%>) create(eClass);
      <%if (genFeature.isListType()) {%>
		<%=genFeature.getGetAccessor()%>().add(new<%=genFeature.getCapName()%>);
      <%} else {%>
		set<%=genFeature.getAccessorName()%>(new<%=genFeature.getCapName()%>);
      <%}%>
      <%for (Iterator k = UML2GenModelUtil.getKeyGenFeatures(genFeature.getTypeGenClass()).iterator(); k.hasNext(); index++) { GenFeature keyGenFeature = (GenFeature) k.next();%>
        <%if (keyGenFeature.isContains()) { List nestedKeyGenFeatures = UML2GenModelUtil.getKeyGenFeatures(keyGenFeature.getTypeGenClass(), false); boolean first = true;%>
          <%if (keyGenFeature.isListType()) {%>
		int <%=keyGenFeature.getUncapName()%>ListSize = 0;
            <%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { n.next();%>
		int <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size = <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> == null ? 0 : <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.size();
		if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size > <%=keyGenFeature.getUncapName()%>ListSize)
			<%=keyGenFeature.getUncapName()%>ListSize = <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size;
            <%}%>
		for (int i = 0; i < <%=keyGenFeature.getUncapName()%>ListSize; i++) {
			new<%=genFeature.getCapName()%>.create<%=keyGenFeature.getCapName()%>(<%for (int n = nestedKeyGenFeatures.size(); n > 0; n--) { GenFeature nestedKeyGenFeature = (GenFeature) nestedKeyGenFeatures.get(nestedKeyGenFeatures.size() - n);%><%if (first) { first = false; } else {%>, <%}%>i < <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index - n, false)%>Size ? (<%=nestedKeyGenFeature.getImportedType()%>) <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index - n, false)%>.get(i) : null<%}%>);
		}
          <%} else {%>
		new<%=genFeature.getCapName()%>.create<%=keyGenFeature.getCapName()%>(<%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { n.next();%><%if (first) { first = false; } else {%>, <%}%><%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%><%}%>);
          <%}%>
        <%} else {%>
		if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null)
          <%if (keyGenFeature.isListType()) {%>
			new<%=genFeature.getCapName()%>.<%=keyGenFeature.getGetAccessor()%>().addAll(<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>);
          <%} else {%>
			new<%=genFeature.getCapName()%>.set<%=keyGenFeature.getAccessorName()%>(<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>);
          <%}%>
        <%}%>
      <%}%>
		return new<%=genFeature.getCapName()%>;
	}

    <%}%>
  <%}%>
  <%if (genClass.getChildrenClasses(genFeature).size() == 1 || !genFeature.getTypeGenClass().isAbstract()) { GenClass childGenClass = (GenClass) genClass.getChildrenClasses(genFeature).get(0);%>
    <%if (isInterface) {%>
	/**
      <%if (!keyGenFeatures.isEmpty()) {%>
        <%if (genFeature.isListType()) {%>
	 * Creates a new {@link <%=childGenClass.getQualifiedInterfaceName()%>}, with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, and appends it to the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%} else {%>
	 * Creates a new {@link <%=childGenClass.getQualifiedInterfaceName()%>},with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, and sets the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%}%>
      <%} else {%>
        <%if (genFeature.isListType()) {%>
	 * Creates a new {@link <%=childGenClass.getQualifiedInterfaceName()%>} and appends it to the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%} else {%>
	 * Creates a new {@link <%=childGenClass.getQualifiedInterfaceName()%>} and sets the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
        <%}%>
      <%}%>
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
      <%for (int index = 0, size = keyGenFeatures.size(); index < size; index++) {%>
	 * @param <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> The <%=UML2GenModelUtil.getFormattedKeyFeatureName(genFeature, index)%> for the new {@link <%=genFeature.getQualifiedListItemType()%>}, or <code>null</code>.
      <%}%>
	 * @return The new {@link <%=childGenClass.getQualifiedInterfaceName()%>}.
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 */
    <%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%}%>
    <%if (!isImplementation) {%>
	<%=genFeature.getListItemType()%> create<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>);

    <%} else { int index = 0;%>
      <%if (genModel.useClassOverrideAnnotation() && UML2GenModelUtil.isDuplicate(genFeature) && !UML2GenModelUtil.isRedefinition(genFeature)) {%>
	@Override
      <%}%>
	public <%=genFeature.getListItemType()%> create<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>)
	{
      <%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>
		return create<%=genFeature.getCapName()%>(<%if (!keyGenFeatures.isEmpty()) {%><%=UML2GenModelUtil.getKeyFeatureParameters(genFeature, false)%>, <%}%><%=genFeature.getTypeGenClass().getQualifiedClassifierAccessor()%>);
      <%} else {%>
		<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%> new<%=genFeature.getCapName()%> = (<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%>) create(<%=genFeature.getTypeGenClass().getQualifiedClassifierAccessor()%>);
        <%if (genFeature.isListType()) {%>
		<%=genFeature.getGetAccessor()%>().add(new<%=genFeature.getCapName()%>);
        <%} else {%>
		set<%=genFeature.getAccessorName()%>(new<%=genFeature.getCapName()%>);
        <%}%>
        <%for (Iterator k = UML2GenModelUtil.getKeyGenFeatures(genFeature.getTypeGenClass()).iterator(); k.hasNext(); index++) { GenFeature keyGenFeature = (GenFeature) k.next();%>
          <%if (keyGenFeature.isContains()) { List nestedKeyGenFeatures = UML2GenModelUtil.getKeyGenFeatures(keyGenFeature.getTypeGenClass(), false); boolean first = true;%>
            <%if (keyGenFeature.isListType()) {%>
		int <%=keyGenFeature.getUncapName()%>ListSize = 0;
              <%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { n.next();%>
		int <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size = <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> == null ? 0 : <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.size();
		if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size > <%=keyGenFeature.getUncapName()%>ListSize)
			<%=keyGenFeature.getUncapName()%>ListSize = <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>Size;
              <%}%>
		for (int i = 0; i < <%=keyGenFeature.getUncapName()%>ListSize; i++) {
			new<%=genFeature.getCapName()%>.create<%=keyGenFeature.getCapName()%>(<%for (int n = nestedKeyGenFeatures.size(); n > 0; n--) { GenFeature nestedKeyGenFeature = (GenFeature) nestedKeyGenFeatures.get(nestedKeyGenFeatures.size() - n);%><%if (first) { first = false; } else {%>, <%}%>i < <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index - n, false)%>Size ? (<%=nestedKeyGenFeature.getImportedType()%>) <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index - n, false)%>.get(i) : null<%}%>);
		}
            <%} else {%>
		new<%=genFeature.getCapName()%>.create<%=keyGenFeature.getCapName()%>(<%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { n.next();%><%if (first) { first = false; } else {%>, <%}%><%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%><%}%>);
            <%}%>
          <%} else {%>
		if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null)
            <%if (keyGenFeature.isListType()) {%>
			new<%=genFeature.getCapName()%>.<%=keyGenFeature.getGetAccessor()%>().addAll(<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>);
            <%} else {%>
			new<%=genFeature.getCapName()%>.set<%=keyGenFeature.getAccessorName()%>(<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>);
            <%}%>
          <%}%>
        <%}%>
		return new<%=genFeature.getCapName()%>;
      <%}%>
	}

    <%}%>
  <%}%>
<%}%>
<%if (!genClass.getExtendedGenFeatures().contains(genFeature) && genFeature.isListType() && genFeature.isReferenceType()) { List keyGenFeatures = UML2GenModelUtil.getKeyGenFeatures(genFeature);%>
  <%if (!keyGenFeatures.isEmpty()) {%>
    <%if (UML2GenModelUtil.hasStringTypeKeyGenFeature(genFeature) || UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>
      <%if (isInterface) {%>
	/**
	 * Retrieves the first {@link <%=genFeature.getQualifiedListItemType()%>} with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%> from the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
        <%for (int index = 0, size = keyGenFeatures.size(); index < size; index++) {%>
	 * @param <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> The <%=UML2GenModelUtil.getFormattedKeyFeatureName(genFeature, index)%> of the {@link <%=genFeature.getQualifiedListItemType()%>} to retrieve, or <code>null</code>.
        <%}%>
	 * @return The first {@link <%=genFeature.getQualifiedListItemType()%>} with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, or <code>null</code>.
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 */
      <%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
      <%}%>
      <%if (!isImplementation) {%>
	<%=genFeature.getListItemType()%> get<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>);

      <%} else {%>
      <%if (genModel.useClassOverrideAnnotation() && UML2GenModelUtil.isDuplicate(genFeature) && !UML2GenModelUtil.isRedefinition(genFeature)) {%>
	@Override
      <%}%>
	public <%=genFeature.getListItemType()%> get<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%>)
	{
		return get<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature, false)%><%if (UML2GenModelUtil.hasStringTypeKeyGenFeature(genFeature)) {%>, false<%}%><%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>, null<%}%><%if (UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>, false<%}%>);
	}

      <%}%>
    <%}%>
    <%if (isInterface) {%>
	/**
	 * Retrieves the first {@link <%=genFeature.getQualifiedListItemType()%>} with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%> from the '<em><b><%=genFeature.getFormattedName()%></b></em>' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
      <%for (int index = 0, size = keyGenFeatures.size(); index < size; index++) {%>
	 * @param <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> The <%=UML2GenModelUtil.getFormattedKeyFeatureName(genFeature, index)%> of the {@link <%=genFeature.getQualifiedListItemType()%>} to retrieve, or <code>null</code>.
      <%}%>
      <%if (UML2GenModelUtil.hasStringTypeKeyGenFeature(genFeature)) {%>
	 * @param ignoreCase Whether to ignore case in {@link java.lang.String} comparisons.
      <%}%>
      <%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>
	 * @param eClass The Ecore class of the {@link <%=genFeature.getQualifiedListItemType()%>} to retrieve, or <code>null</code>.
      <%}%>
      <%if (UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>
	 * @param createOnDemand Whether to create a {@link <%=genFeature.getQualifiedListItemType()%>} on demand if not found.
      <%}%>
	 * @return The first {@link <%=genFeature.getQualifiedListItemType()%>} with the specified <%=UML2GenModelUtil.getFormattedKeyFeatureNames(genFeature)%>, or <code>null</code>.
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 */
    <%} else {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
    <%}%>
    <%if (!isImplementation) {%>
	<%=genFeature.getListItemType()%> get<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%><%if (UML2GenModelUtil.hasStringTypeKeyGenFeature(genFeature)) {%>, boolean ignoreCase<%}%><%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>, <%=genModel.getImportedName("org.eclipse.emf.ecore.EClass")%> eClass<%}%><%if (UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>, boolean createOnDemand<%}%>);

    <%} else { int index = 0;%>
      <%if (genModel.useClassOverrideAnnotation() && UML2GenModelUtil.isDuplicate(genFeature) && !UML2GenModelUtil.isRedefinition(genFeature)) {%>
	@Override
      <%}%>
	public <%=genFeature.getListItemType()%> get<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature)%><%if (UML2GenModelUtil.hasStringTypeKeyGenFeature(genFeature)) {%>, boolean ignoreCase<%}%><%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>, <%=genModel.getImportedName("org.eclipse.emf.ecore.EClass")%> eClass<%}%><%if (UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>, boolean createOnDemand<%}%>)
	{
      <%if (genModel.getComplianceLevel().getValue() >= GenJDKLevel.JDK50) {%>
		<%=genFeature.getUncapName()%>Loop: for (<%=genModel.getImportedName(genFeature.getListItemType())%> <%=genFeature.getUncapName()%> : <%=genFeature.getGetAccessor()%>())
		{
      <%} else {%>
		<%=genFeature.getUncapName()%>Loop: for (<%=genModel.getImportedName("java.util.Iterator")%> i = <%=genFeature.getGetAccessor()%>().iterator(); i.hasNext(); )
		{
			<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%> <%=genFeature.getUncapName()%> = (<%=genModel.getImportedName(genFeature.getQualifiedListItemType())%>) i.next();
      <%}%>
      <%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>
			if (eClass != null && !eClass.isInstance(<%=genFeature.getUncapName()%>))
				continue <%=genFeature.getUncapName()%>Loop;
      <%}%>
      <%for (Iterator k = UML2GenModelUtil.getKeyGenFeatures(genFeature.getTypeGenClass()).iterator(); k.hasNext(); index++) { GenFeature keyGenFeature = (GenFeature) k.next();%>
        <%if (keyGenFeature.isContains()) { List nestedKeyGenFeatures = UML2GenModelUtil.getKeyGenFeatures(keyGenFeature.getTypeGenClass(), false); boolean first = true;%>
          <%if (keyGenFeature.isListType()) {%>
			<%=keyGenFeature.getImportedType()%> <%=keyGenFeature.getUncapName()%>List = <%=genFeature.getUncapName()%>.<%=keyGenFeature.getGetAccessor()%>();
			int <%=keyGenFeature.getUncapName()%>ListSize = <%=keyGenFeature.getUncapName()%>List.size();
			if (<%for (int n = 0, size = nestedKeyGenFeatures.size(); n < size; n++) {%><%if (!first) {%> || (<%}%><%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index + n, false)%> != null && <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index + n, false)%>.size() != <%=keyGenFeature.getUncapName()%>ListSize<%if (first) {first = false;%><%} else {%>)<%}%><%}%>)
				continue  <%=genFeature.getUncapName()%>Loop;
			for (int j = 0; j < <%=keyGenFeature.getUncapName()%>ListSize; j++)
			{
				<%=genModel.getImportedName(keyGenFeature.getQualifiedListItemType())%> <%=keyGenFeature.getUncapName()%> = <%if (genModel.getComplianceLevel().getValue() < GenJDKLevel.JDK50) {%>(<%=genModel.getImportedName(keyGenFeature.getQualifiedListItemType())%>) <%}%><%=keyGenFeature.getUncapName()%>List.get(j);
            <%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { GenFeature nestedKeyGenFeature = (GenFeature) n.next();%>
              <%if (nestedKeyGenFeature.isStringType()) {%>
				if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !(ignoreCase ? (<%if (genModel.getComplianceLevel().getValue() < GenJDKLevel.JDK50) {%>(<%=genModel.getImportedName("java.lang.String")%>)<%}%><%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.get(j)).equalsIgnoreCase(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>()) : <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.get(j).equals(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>())))
              <%} else {%>
				if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.get(j).equals(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>()))
              <%}%>
					continue <%=genFeature.getUncapName()%>Loop;
            <%}%>
			}
          <%} else {%>
			<%=keyGenFeature.getImportedType()%> <%=keyGenFeature.getUncapName()%> = <%=genFeature.getUncapName()%>.<%=keyGenFeature.getGetAccessor()%>();
			if (<%=keyGenFeature.getUncapName()%> == null)
				continue <%=genFeature.getUncapName()%>Loop;
            <%for (Iterator n = nestedKeyGenFeatures.iterator(); n.hasNext(); index++) { GenFeature nestedKeyGenFeature = (GenFeature) n.next();%>
              <%if (nestedKeyGenFeature.isStringType()) {%>
			if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !(ignoreCase ? <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equalsIgnoreCase(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>()) : <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equals(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>())))
              <%} else {%>
			if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equals(<%=keyGenFeature.getUncapName()%>.<%=nestedKeyGenFeature.getGetAccessor()%>()))
              <%}%>
				continue <%=genFeature.getUncapName()%>Loop;
            <%}%>
          <%}%>
        <%} else {%>
          <%if (keyGenFeature.isStringType()) {%>
			if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !(ignoreCase ? <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equalsIgnoreCase(<%=genFeature.getUncapName()%>.<%=keyGenFeature.getGetAccessor()%>()) : <%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equals(<%=genFeature.getUncapName()%>.<%=keyGenFeature.getGetAccessor()%>())))
          <%} else {%>
			if (<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%> != null && !<%=UML2GenModelUtil.getKeyFeatureParameter(genFeature, index, false)%>.equals(<%=genFeature.getUncapName()%>.<%=keyGenFeature.getGetAccessor()%>()))
          <%}%>
				continue <%=genFeature.getUncapName()%>Loop;
        <%}%>
      <%}%>
			return <%=genFeature.getUncapName()%>;
		}
      <%if (UML2GenModelUtil.isFactoryMethods(genClass, genFeature)) {%>
		return createOnDemand<%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%> && eClass != null<%}%> ? create<%=genFeature.getCapName()%>(<%=UML2GenModelUtil.getKeyFeatureParameters(genFeature, false)%><%if (genClass.getChildrenClasses(genFeature).size() > 1 || genFeature.getTypeGenClass().isAbstract()) {%>, eClass<%}%>) : null;
      <%} else {%>
		return null;
      <%}%>
	}

    <%}%>
  <%}%>
<%}%>
<%if (isImplementation && ((UML2GenModelUtil.isRedefinition(genFeature) && !genFeature.isIsSet()) || UML2GenModelUtil.isRedefined(genClass, genFeature))) {%>
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
  <%if (genModel.useClassOverrideAnnotation() && UML2GenModelUtil.isDuplicate(genFeature) && !UML2GenModelUtil.isRedefinition(genFeature)) {%>
	@Override
  <%}%>
	public boolean isSet<%=genFeature.getAccessorName()%>()
	{
  <%if (!genFeature.isUnsettable()) {%>
    <%if (UML2GenModelUtil.isRedefined(genClass, genFeature)) {%>
  		return false;
    <%} else if (genModel.isReflectiveDelegation()) {%>
		return eIsSet(<%=genFeature.getQualifiedFeatureAccessor()%>);
    <%} else if (genFeature.isListType()) {%>
      <%if (genFeature.isWrappedFeatureMapType()) {%>
        <%if (genFeature.isVolatile()) {%>
		return !((<%=genModel.getImportedName("org.eclipse.emf.ecore.util.FeatureMap")%>.Internal.Wrapper)<%=genFeature.getGetAccessor()%>()).featureMap().isEmpty();
        <%} else {%>
		return <%=genFeature.getSafeName()%> != null && !<%=genFeature.getSafeName()%>.featureMap().isEmpty();
        <%}%>
      <%} else {%>
        <%if (genClass.isField(genFeature)) {%>
		return <%=genFeature.getSafeName()%> != null && !<%=genFeature.getSafeName()%>.isEmpty();
        <%} else {%>
          <%if (genFeature.isField() && genClass.getImplementingGenModel(genFeature).isVirtualDelegation()) {%>
		<%=genFeature.getImportedType()%> <%=genFeature.getSafeName()%> = (<%=genFeature.getImportedType()%>)eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>);
		return <%=genFeature.getSafeName()%> != null && !<%=genFeature.getSafeName()%>.isEmpty();
          <%} else {%>
		return !<%=genFeature.getGetAccessor()%>().isEmpty();
          <%}%>
        <%}%>
      <%}%>
    <%} else if (genFeature.isResolveProxies()) {%>
      <%if (genClass.isField(genFeature)) {%>
		return <%=genFeature.getSafeName()%> != null;
      <%} else {%>
        <%if (genFeature.isField() && genClass.getImplementingGenModel(genFeature).isVirtualDelegation()) {%>
		return eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>) != null;
        <%} else {%>
		return basicGet<%=genFeature.getAccessorName()%>() != null;
        <%}%>
      <%}%>
    <%} else if (genFeature.isReferenceType()) {%>
      <%if (genClass.isField(genFeature)) {%>
		return <%=genFeature.getSafeName()%> != null;
      <%} else {%>
        <%if (genFeature.isField() && genClass.getImplementingGenModel(genFeature).isVirtualDelegation()) {%>
		return eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>) != null;
        <%} else {%>
		return <%=genFeature.getGetAccessor()%>() != null;
        <%}%>
      <%}%>
    <%} else if (genFeature.isPrimitiveType() || genFeature.isEnumType()) {%>
      <%if (genClass.isField(genFeature)) {%>
        <%if (genClass.isFlag(genFeature)) {%>
		return ((<%=genClass.getFlagsField(genFeature)%> & <%=genFeature.getUpperName()%>_EFLAG) != 0) != <%=genFeature.getEDefault()%>;
        <%} else {%>
		return <%=genFeature.getSafeName()%> != <%=genFeature.getEDefault()%>;
        <%}%>
      <%} else {%>
        <%if (genFeature.isEnumType() && genFeature.isField() && genClass.getImplementingGenModel(genFeature).isVirtualDelegation()) {%>
		return eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>, <%=genFeature.getEDefault()%>) != <%=genFeature.getEDefault()%>;
        <%} else {%>
		return <%=genFeature.getGetAccessor()%>() != <%=genFeature.getEDefault()%>;
        <%}%>
      <%}%>
    <%} else {//datatype%>
      <%if (genClass.isField(genFeature)) {%>
		return <%=genFeature.getEDefault()%> == null ? <%=genFeature.getSafeName()%> != null : !<%=genFeature.getEDefault()%>.equals(<%=genFeature.getSafeName()%>);
      <%} else {%>
        <%if (genFeature.isField() && genClass.getImplementingGenModel(genFeature).isVirtualDelegation()) {%>
		<%=genFeature.getImportedType()%> <%=genFeature.getSafeName()%> = (<%=genFeature.getImportedType()%>)eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>, <%=genFeature.getEDefault()%>);
		return <%=genFeature.getEDefault()%> == null ? <%=genFeature.getSafeName()%> != null : !<%=genFeature.getEDefault()%>.equals(<%=genFeature.getSafeName()%>);
        <%} else {%>
		return <%=genFeature.getEDefault()%> == null ? <%=genFeature.getGetAccessor()%>() != null : !<%=genFeature.getEDefault()%>.equals(<%=genFeature.getGetAccessor()%>());
        <%}%>
      <%}%>
    <%}%>
  <%} else {%>
    <%if (genModel.isReflectiveDelegation()) {%>
		return eIsSet(<%=genFeature.getQualifiedFeatureAccessor()%>);
    <%} else if (!genFeature.isVolatile()) {%>
      <%if (genFeature.isListType()) {%>
        <%if (genModel.isVirtualDelegation()) {%>
		<%=genFeature.getImportedType()%> <%=genFeature.getSafeName()%> = (<%=genFeature.getImportedType()%>)eVirtualGet(<%=genClass.getQualifiedFeatureID(genFeature)%>);
        <%}%>
		return <%=genFeature.getSafeName()%> != null && ((<%=genModel.getImportedName("org.eclipse.emf.ecore.util.InternalEList")%>.Unsettable<%=singleWildcard%>)<%=genFeature.getSafeName()%>).isSet();
      <%} else {%>
        <%if (genModel.isVirtualDelegation() && !genFeature.isPrimitiveType()) {%>
		return eVirtualIsSet(<%=genClass.getQualifiedFeatureID(genFeature)%>);
        <%} else if (genClass.isESetFlag(genFeature)) {%>
		return (<%=genClass.getESetFlagsField(genFeature)%> & <%=genFeature.getUpperName()%>_ESETFLAG) != 0;
        <%} else {%>
		return <%=genFeature.getUncapName()%>ESet;
        <%}%>
      <%}%>
    <%} else if (genFeature.hasDelegateFeature()) { GenFeature delegateFeature = genFeature.getDelegateFeature();%>
      <%if (delegateFeature.isWrappedFeatureMapType()) {%>
		return !((<%=genModel.getImportedName("org.eclipse.emf.ecore.util.FeatureMap")%>.Internal)((<%=genModel.getImportedName("org.eclipse.emf.ecore.util.FeatureMap")%>.Internal.Wrapper)get<%=delegateFeature.getAccessorName()%>()).featureMap()).isEmpty(<%=genFeature.getQualifiedFeatureAccessor()%>);
      <%} else {%>
		return !((<%=genModel.getImportedName("org.eclipse.emf.ecore.util.FeatureMap")%>.Internal)get<%=delegateFeature.getAccessorName()%>()).isEmpty(<%=genFeature.getQualifiedFeatureAccessor()%>);
      <%}%>
    <%} else {%>
<%@ include file="isSetGenFeature.TODO.override.javajetinc" fail="alternative" %>
<%@ start %>
		// TODO: implement this method to return whether the '<%=genFeature.getFormattedName()%>' <%=genFeature.getFeatureKind()%> is set
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
<%@ end %><%//isSetGenFeature.todo.override.javajetinc%>
    <%}%>
  <%}%>
	}

<%}%>