/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 * Copyright (C) 2014-2026 SARL.io, the original authors and main authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sarl.lang.tests.general.compilation.aop;

import static io.sarl.tests.api.tools.TestEObjects.file;
import static io.sarl.tests.api.tools.TestUtils.multilineString;
import static io.sarl.tests.api.tools.TestValidator.validate;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import io.sarl.lang.core.SARLVersion;
import io.sarl.lang.core.Event.Bound;
import io.sarl.lang.sarl.SarlPackage;
import io.sarl.lang.sarl.SarlScript;
import io.sarl.lang.tests.api.AbstractSarlTest;

/**
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 * @since 0.14
 */
@DisplayName("Compilation: generic Event")
@Tag("core")
@Tag("sarlValidation")
@SuppressWarnings("all")
public class GenericEventCompilerTest {

	@DisplayName("Direct Event inheritance")
	@Nested
	public class DirectEventInheritance extends AbstractSarlTest {

		@Test
		@DisplayName("Empty event with block")
		public void basicCompile_withBlock() throws Exception {
			String source = "event E1<T1, T2 extends Number, T3 extends Double> { }";
			String expected = multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""
					);
			getCompileHelper().assertCompilesTo(source, expected);
		}
	
		@Test
		@DisplayName("Empty event without block")
		public void basicCompile_withoutBlock() throws Exception {
			String source = "event E1<T1, T2 extends Number, T3 extends Double>";
			String expected = multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""
					);
			getCompileHelper().assertCompilesTo(source, expected);
		}
	
		@Test
		@DisplayName("With string field")
		public void withVarAttributesCompile() throws Exception {
			String source = multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"  var name : String",
					"}"
					);
			String expected = multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticEventConstructor;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import java.util.Objects;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public String name;",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1(final String name) {",
					"    super();",
					"    this.name = name;",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public boolean equals(final Object obj) {",
					"    if (this == obj)",
					"      return true;",
					"    if (obj == null)",
					"      return false;",
					"    if (getClass() != obj.getClass())",
					"      return false;",
					"    E1 other = (E1) obj;",
					"    if (!Objects.equals(this.name, other.name))",
					"      return false;",
					"    return super.equals(obj);",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public int hashCode() {",
					"    int result = super.hashCode();",
					"    final int prime = 31;",
					"    result = prime * result + Objects.hashCode(this.name);",
					"    return result;",
					"  }",
					"  ",
					"  /**",
					"   * Returns a String representation of the E1 event's attributes only.",
					"   */",
					"  @SyntheticMember",
					"  @Pure",
					"  protected void toString(final ToStringBuilder builder) {",
					"    super.toString(builder);",
					"    builder.add(\"name\", this.name);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 1787001662L;",
					"}",
					""
					);
			getCompileHelper().assertCompilesTo(source, expected);
		}

		@Test
		@DisplayName("With constructor")
		public void noStaticField() throws Exception {
			String source = multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	val titi : int = 4",
					"	val toto : int",
					"	new(a : int) {",
					"		this.toto = a",
					"	}",
					"}"
					);
			String expected = multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public final int titi = 4;",
					"  ",
					"  public final int toto;",
					"  ",
					"  public E1(final int a) {",
					"    this.toto = a;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public boolean equals(final Object obj) {",
					"    if (this == obj)",
					"      return true;",
					"    if (obj == null)",
					"      return false;",
					"    if (getClass() != obj.getClass())",
					"      return false;",
					"    E1 other = (E1) obj;",
					"    if (other.titi != this.titi)",
					"      return false;",
					"    if (other.toto != this.toto)",
					"      return false;",
					"    return super.equals(obj);",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public int hashCode() {",
					"    int result = super.hashCode();",
					"    final int prime = 31;",
					"    result = prime * result + Integer.hashCode(this.titi);",
					"    result = prime * result + Integer.hashCode(this.toto);",
					"    return result;",
					"  }",
					"  ",
					"  /**",
					"   * Returns a String representation of the E1 event's attributes only.",
					"   */",
					"  @SyntheticMember",
					"  @Pure",
					"  protected void toString(final ToStringBuilder builder) {",
					"    super.toString(builder);",
					"    builder.add(\"titi\", this.titi);", 
					"    builder.add(\"toto\", this.toto);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 598944340L;",
					"}",
					""
					);
			getCompileHelper().assertCompilesTo(source, expected);
		}

		@Test
		@DisplayName("Without modifier")
		public void eventmodifier_none() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double>"
				),
				multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("With public modifier")
		public void eventmodifier_public() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"public event E1<T1, T2 extends Number, T3 extends Double>"
				),
				multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""));
		}

		@Test
		@DisplayName("With abstract modifier")
		public void eventmodifier_abstract() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"abstract event E1<T1, T2 extends Number, T3 extends Double>"
				),
				multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public abstract class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("With package modifier")
		public void eventmodifier_package() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"package event E1<T1, T2 extends Number, T3 extends Double>"
				),
				multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("With final modifier")
		public void eventmodifier_final() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"final event E1<T1, T2 extends Number, T3 extends Double>"
				),
				multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public final class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  public E1(final Address arg0) {",
					"    super(arg0);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588368462L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("Without field modifier")
		public void fieldmodifier_none() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	var field : int",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticEventConstructor;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public int field;",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1(final int field) {",
					"    super();",
					"    this.field = field;",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public boolean equals(final Object obj) {",
					"    if (this == obj)",
					"      return true;",
					"    if (obj == null)",
					"      return false;",
					"    if (getClass() != obj.getClass())",
					"      return false;",
					"    E1 other = (E1) obj;",
					"    if (other.field != this.field)",
					"      return false;",
					"    return super.equals(obj);",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public int hashCode() {",
					"    int result = super.hashCode();",
					"    final int prime = 31;",
					"    result = prime * result + Integer.hashCode(this.field);",
					"    return result;",
					"  }",
					"  ",
					"  /**",
					"   * Returns a String representation of the E1 event's attributes only.",
					"   */",
					"  @SyntheticMember",
					"  @Pure",
					"  protected void toString(final ToStringBuilder builder) {",
					"    super.toString(builder);",
					"    builder.add(\"field\", this.field);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 685900599L;",
					"}",
					""));
		}

		@Test
		@DisplayName("With public field modifier")
		public void fieldmodifier_public() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	public var field : int",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticEventConstructor;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public int field;",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1() {",
					"    super();",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @SyntheticEventConstructor",
					"  public E1(final int field) {",
					"    super();",
					"    this.field = field;",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public boolean equals(final Object obj) {",
					"    if (this == obj)",
					"      return true;",
					"    if (obj == null)",
					"      return false;",
					"    if (getClass() != obj.getClass())",
					"      return false;",
					"    E1 other = (E1) obj;",
					"    if (other.field != this.field)",
					"      return false;",
					"    return super.equals(obj);",
					"  }",
					"  ",
					"  @Override",
					"  @Pure",
					"  @SyntheticMember",
					"  public int hashCode() {",
					"    int result = super.hashCode();",
					"    final int prime = 31;",
					"    result = prime * result + Integer.hashCode(this.field);",
					"    return result;",
					"  }",
					"  ",
					"  /**",
					"   * Returns a String representation of the E1 event's attributes only.",
					"   */",
					"  @SyntheticMember",
					"  @Pure",
					"  protected void toString(final ToStringBuilder builder) {",
					"    super.toString(builder);",
					"    builder.add(\"field\", this.field);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 685900599L;",
					"}",
					""));
		}

		@Test
		@DisplayName("Without constructor modifier")
		public void constructormodifier_none() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	new { super(null) }",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public E1() {",
					"    super(null);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588370691L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("With public constructor modifier")
		public void constructormodifier_public() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	public new { super(null) }",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  public E1() {",
					"    super(null);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588370691L;",
					"}",
					""));
		}

		@Test
		@DisplayName("With private constructor modifier")
		public void constructormodifier_private() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	private new { super(null) }",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  private E1() {",
					"    super(null);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588370691L;",
					"}",
					""));
		}
	
		@Test
		@DisplayName("With package constructor modifier")
		public void constructormodifier_package() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	package new { super(null) }",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  E1() {",
					"    super(null);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588370691L;",
					"}",
					""));
		}

		@Test
		@DisplayName("With protected constructor modifier")
		public void constructormodifier_protected() throws Exception {
			getCompileHelper().assertCompilesTo(
				multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> {",
					"	protected new { super(null) }",
					"}"
				),
				multilineString(
					"import io.sarl.lang.core.Event;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
					"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
					"@SarlElementType(" + SarlPackage.SARL_EVENT + ")",
					"@XbaseGenerated",
					"@SuppressWarnings(\"all\")",
					"public class E1<T1 extends Object, T2 extends Number, T3 extends Double> extends Event {",
					"  protected E1() {",
					"    super(null);",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  @Pure",
					"  public static boolean $matchesTypeBounds(final E1<?, ?, ?> it, final Class<?>... bounds) {",
					"    if (bounds != null && bounds.length == 3) {",
					"      return true;",
					"    }",
					"    return false;",
					"  }",
					"  ",
					"  @SyntheticMember",
					"  private static final long serialVersionUID = 588370691L;",
					"}",
					""));
		}

	}

	@DisplayName("Same super generic prototype")
	@Nested
	public class SameGenericEventInheritance extends AbstractSarlTest {

		@Test
		@DisplayName("Empty event with block")
		public void basicCompile_withBlock() throws Exception {
			String source = multilineString(
					"event E1<T1, T2 extends Number, T3 extends Double> { }",
					"event E2<T1 extends Object, T2 extends Number, T3 extends Double> extends E1<T1, T2, T3> { }");
			String expected = multilineString(
					"import io.sarl.lang.core.Address;",
					"import io.sarl.lang.core.annotation.SarlElementType;",
					"import io.sarl.lang.core.annotation.SarlSpecification;",
					"import io.sarl.lang.core.annotation.SyntheticMember;",
					"import org.eclipse.xtext.xbase.lib.Pure;",
					"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
					"",
