/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors:
 *   Balasko, Jeno
 *   Raduly, Csaba
 *   Szabados, Kristof
 *   Szabo, Janos Zoltan – initial implementation
 *
 ******************************************************************************/
module TtemplateEnum {
type component templateEnum_mycomp {};
type enumerated templateEnum_myenum {xx1,xx2,xx3,xx4,xx5,xx6,xx7};
type record templateEnum_rec {
 templateEnum_myenum x1,
 templateEnum_myenum x2,
 templateEnum_myenum x3 optional };
template templateEnum_rec templateEnum_tSpec :={ //specific values
 x1:=xx1,
 x2:=xx2,
 x3:=xx3 };
template templateEnum_rec templateEnum_tList :={ //specific value and value list
 x1:=xx1,
 x2:=(xx2,xx3,xx6),
 x3:=xx3 };
template templateEnum_rec templateEnum_tComp :={ //specific value and compl. list
 x1:=xx1,
 x2:=complement (xx2,xx3,xx6),
 x3:=xx3 };
template templateEnum_rec templateEnum_tOmit :={ //omitting values
 x1:=xx1,
 x2:=xx2,
 x3:=omit } ;
template templateEnum_rec templateEnum_tAny :={ //specific and any value
 x1:=xx1,
 x2:=xx2,
 x3:=? } ;
template templateEnum_rec templateEnum_tAnyorNone :={ //specific and AnyorNone value
 x1:=xx1,
 x2:=xx2,
 x3:=* };
template templateEnum_rec templateEnum_tIfpresent :={ //specific value and ifpresent
 x1:=xx1,
 x2:=xx2,
 x3:=xx3 ifpresent };

testcase templateEnumSpec() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2;		//specific value
x1:={ x1:=xx1,  x2:=xx2,  x3:=xx3 };
x2:={ x1:=xx2,  x2:=xx2,  x3:=xx3 };
//match
if (match(x1,templateEnum_tSpec)) {setverdict(pass);}
 else {setverdict(fail);}
//no match
if (not(match(x2,templateEnum_tSpec))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumList() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3;		//value list
x1:={ x1:=xx1,  x2:=xx6,  x3:=xx3 };
x2:={ x1:=xx1,  x2:=xx7,  x3:=xx3 };
x3:={ x1:=xx2,  x2:=xx6,  x3:=xx3 };
//match
if (match(x1,templateEnum_tList)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: out of list
if (not(match(x2,templateEnum_tList))) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x3,templateEnum_tList))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumComp() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3;		//complemented list
x1:={ x1:=xx1,  x2:=xx7,  x3:=xx3 };
x2:={ x1:=xx1,  x2:=xx6,  x3:=xx3 };
x3:={ x1:=xx2,  x2:=xx7,  x3:=xx3 };
//match
if (match(x1,templateEnum_tComp)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: in the list
if (not(match(x2,templateEnum_tComp))) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x3,templateEnum_tComp))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumOmit() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3;		//omitting value
x1:={ x1:=xx1,  x2:=xx2,  x3:=omit };
x2:={ x1:=xx1,  x2:=xx2,  x3:=xx3 };
x3:={ x1:=xx2,  x2:=xx2,  x3:=omit };
//match
if (match(x1,templateEnum_tOmit)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: not omitted
if (not(match(x2,templateEnum_tOmit))) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x3,templateEnum_tOmit))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumAny() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3;		//any value
x1:={ x1:=xx1,  x2:=xx2,  x3:=xx3 };
x2:={ x1:=xx2,  x2:=xx2,  x3:=xx3 };
x3:={ x1:=xx1,  x2:=xx2,  x3:=omit };
//match
if (match(x1,templateEnum_tAny)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: field omitted
if (not(match(x2,templateEnum_tAny))) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x3,templateEnum_tAny))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumAnyorNone() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3;		//AnyorNone value
x1:={ x1:=xx1,  x2:=xx2,  x3:=omit };
x2:={ x1:=xx1,  x2:=xx2,  x3:=xx3 };
x3:={ x1:=xx2,  x2:=xx2,  x3:=omit };
//match: omitted
if (match(x1,templateEnum_tAnyorNone)) {setverdict(pass);}
 else {setverdict(fail);}
//match: value
if (match(x2,templateEnum_tAnyorNone)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x3,templateEnum_tAnyorNone))) {setverdict(pass);}
 else {setverdict(fail);}
}

testcase templateEnumIfpresent() runs on templateEnum_mycomp {
var templateEnum_rec x1,x2,x3,x4;		//ifpresent
x1:={ x1:=xx1,  x2:=xx2,  x3:=xx3 };
x2:={ x1:=xx1,  x2:=xx2,  x3:=omit };
x3:={ x1:=xx2,  x2:=xx2,  x3:=omit };
x4:={ x1:=xx1,  x2:=xx2,  x3:=xx4 };
//match: present and match
if (match(x1,templateEnum_tIfpresent)) {setverdict(pass);}
 else {setverdict(fail);}
//match: not present
if (match(x2,templateEnum_tIfpresent)) {setverdict(pass);}
 else {setverdict(fail);}
//no match: present and not match
if (not(match(x3,templateEnum_tIfpresent))) {setverdict(pass);}
 else {setverdict(fail);}
//no match: other field
if (not(match(x4,templateEnum_tIfpresent))) {setverdict(pass);}
 else {setverdict(fail);}
}

type enumerated Day { Monday(1), Tuesday(2), Wednesday(3), Thursday(4), Friday(5), Saturday(6), Sunday(7) }

function f_is_weekday(Day p_par) return boolean {
  return p_par != Saturday and p_par != Sunday;
}

template Day t_conjunction := conjunct((Monday, Wednesday, Thursday, Saturday), @dynamic f_is_weekday);

template Day t_implication := (Monday, Wednesday, Thursday, Saturday) implies @dynamic f_is_weekday;

// matches if the numeric value of the enumerated item matches the template parameter
template Day t_dynamic(template integer pt_int) := @dynamic {
  return match(enum2int(value), pt_int);
}

testcase templateEnumConjunction() runs on templateEnum_mycomp {
  var Day v1 := Wednesday, v2 := Saturday;
  if (not match(v1, t_conjunction)) {
    setverdict(fail, match(v1, t_conjunction));
  }
  if (match(v2, t_conjunction)) {
    setverdict(fail, match(v2, t_conjunction));
  }
  setverdict(pass);
}

testcase templateEnumImplication() runs on templateEnum_mycomp {
  var Day v1 := Sunday, v2 := Saturday, v3 := Thursday;
  if (not match(v1, t_implication)) {
    setverdict(fail, match(v1, t_implication));
  }
  if (match(v2, t_implication)) {
    setverdict(fail, match(v2, t_implication));
  }
  if (not match(v3, t_implication)) {
    setverdict(fail, match(v3, t_implication));
  }
  setverdict(pass);
}

testcase templateEnumDynamic() runs on templateEnum_mycomp {
  var Day v1 := Saturday, v2 := Thursday;
  var template integer vt1 := (6, 7), vt2 := @dynamic { return value mod 2 == 1; };
  if (not match(v1, t_dynamic(vt1))) {
    setverdict(fail, match(v1, t_dynamic(vt1)));
  }
  if (match(v2, t_dynamic(vt2))) {
    setverdict(fail, match(v2, t_dynamic(vt2)));
  }
  setverdict(pass);
}

control {
 execute(templateEnumSpec());
 execute(templateEnumList());
 execute(templateEnumComp());
 execute(templateEnumOmit());
 execute(templateEnumAny());
 execute(templateEnumAnyorNone());
 execute(templateEnumIfpresent());
 execute(templateEnumConjunction());
 execute(templateEnumImplication());
 execute(templateEnumDynamic());
}
}
