/******************************************************************************
 * 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
 *   Szabo, Bence Janos
 *
 ******************************************************************************/
module Text
{
modulepar boolean Text_verbose := false;
#define verbose Text_verbose
#include "../macros.ttcnin"

type component Plain {}

type enumerated ProductColorT { red(0), light_green(1), blue(2) }
with {
  variant "text 'red' as uppercased";
  variant "text 'light_green' as 'Light Green'"
  variant "text 'blue' as capitalized"
  variant "text 'red' as 'Red!'"; // this used to be in ProductColorTT below
};

type ProductColorT ProductColorTT
// Adding more "text" to existing ones is not supported by Titan.
//with {
//variant "text 'red' as 'Red!'";
//}

type boolean Availability
with {
  variant "text"
}

type record T {
  ProductColorTT color,
  Availability available
}

DECLARE_XER_ENCODERS(T, t);
DECLARE_EXER_ENCODERS(T, t);

const T prod := {
  color := light_green,
  available := true
}

const universal charstring str_t_e :=
"<T>\n" &
"\t<color>Light Green</color>\n" &
"\t<available>1</available>\n" &
// "text all as uppercased" doesn`t work
// only "text" is implemented (for it to be '1')
"</T>\n\n";

const universal charstring str_t_b :=
"<T>\n" &
"\t<color><light_green/></color>\n" &
"\t<available><true/></available>\n" &
"</T>\n\n";

testcase encode_txt() runs on Plain
{
  CHECK_METHOD(bxer_enc_t, prod, str_t_b);
  CHECK_METHOD(exer_enc_t, prod, str_t_e);
}

testcase decode_txt() runs on Plain
{
  CHECK_DECODE(bxer_dec_t, str_t_b, T, prod);
  CHECK_DECODE(exer_dec_t, str_t_e, T, prod);
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//

//type enumerated pi { three(3), fourteen(14), fifteen(15), nine(9), two(2), six(6) }

type enumerated Semaphore { red(0), yellow, green }
with {
  variant "text all as uppercased";
  variant "text 'red' as 'piros'"; // used to be on Crossing.lamp's type
}

DECLARE_XER_ENCODERS(Semaphore, sem)
DECLARE_EXER_ENCODERS(Semaphore, sem)

const Semaphore rot := red;
const Semaphore gelb:= yellow;

const universal charstring bstr_rot :=
"<Semaphore><red/></Semaphore>\n\n";
const universal charstring estr_rot :=
"<Semaphore>piros</Semaphore>\n\n";

const universal charstring bstr_gelb :=
"<Semaphore><yellow/></Semaphore>\n\n";
const universal charstring estr_gelb :=
"<Semaphore>YELLOW</Semaphore>\n\n";

testcase encode_semaphore() runs on Plain
{
  CHECK_METHOD(bxer_enc_sem, rot, bstr_rot);
  CHECK_METHOD(exer_enc_sem, rot, estr_rot);

  CHECK_METHOD(bxer_enc_sem, gelb, bstr_gelb);
  CHECK_METHOD(exer_enc_sem, gelb, estr_gelb);
}

testcase decode_semaphore() runs on Plain
{
  CHECK_DECODE(bxer_dec_sem, bstr_rot, Semaphore, rot);
  CHECK_DECODE(exer_dec_sem, estr_rot, Semaphore, rot);

  CHECK_DECODE(bxer_dec_sem, bstr_gelb, Semaphore, gelb);
  CHECK_DECODE(exer_dec_sem, estr_gelb, Semaphore, gelb);
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

type enumerated Response { brake, accelerate }
with {
  variant "text 'brake' as 'Stop!!'";
  variant "text 'accelerate' as 'Step on it!'"
}

type record Crossing {
  Semaphore lamp,
  Response  reaction
}
//with {
//  variant (lamp) "text 'red' as 'piros'"
//}

DECLARE_XER_ENCODERS(Crossing, c)
DECLARE_EXER_ENCODERS(Crossing, c)

const Crossing y := {
  lamp     := yellow,
  reaction := accelerate
}

const Crossing r := {
  lamp     := red,
  reaction := brake
}

const universal charstring estr_y :=
"<Crossing>\n" &
"\t<lamp>YELLOW</lamp>\n" &
"\t<reaction>Step on it!</reaction>\n" &
"</Crossing>\n\n";

const universal charstring bstr_y :=
"<Crossing>\n" &
"\t<lamp><yellow/></lamp>\n" &
"\t<reaction><accelerate/></reaction>\n" &
"</Crossing>\n\n";

const universal charstring estr_r :=
"<Crossing>\n" &
"\t<lamp>piros</lamp>\n" &
"\t<reaction>Stop!!</reaction>\n" &
"</Crossing>\n\n";

const universal charstring bstr_r :=
"<Crossing>\n" &
"\t<lamp><red/></lamp>\n" &
"\t<reaction><brake/></reaction>\n" &
"</Crossing>\n\n";




testcase encode_cross() runs on Plain
{
  CHECK_METHOD(bxer_enc_c, y, bstr_y);
  CHECK_METHOD(exer_enc_c, y, estr_y);

  CHECK_METHOD(bxer_enc_c, r, bstr_r);
  //overriding of TEXT does not work yet: CHECK_METHOD(exer_enc_x, r, estr_r);
}

testcase decode_cross() runs on Plain
{
  CHECK_DECODE(bxer_dec_c, bstr_y, Crossing, y);
  CHECK_DECODE(exer_dec_c, estr_y, Crossing, y);

  CHECK_DECODE(bxer_dec_c, bstr_r, Crossing, r);
  //overriding of TEXT does not work yet: CHECK_DECODE(exer_dec_x, estr_r, Crossing, r);
}

/* * * * * * * * * * * * * * * * * * * * * * */
// Regression test for HO84974

// A classic enum (not affected by the bug)
type enumerated Truth    { TRUE, FALSE, FILE_NOT_FOUND };

/* A classic enum that could have been defined in XML:

    <xs:simpleType name="XmlTruth">
        <xs:restriction base="xs:string">
            <xs:enumeration value="TRUE"/>
            <xs:enumeration value="FALSE"/>
            <xs:enumeration value="FILE_NOT_FOUND"/>
        </xs:restriction>
    </xs:simpleType>
*/
type enumerated XmlTruth { tRUE, fALSE, fILE_NOT_FOUND }
with {
  variant "text all as capitalized"
}

DECLARE_EXER_ENCODERS(Truth, w);
DECLARE_EXER_ENCODERS(XmlTruth, x);

const Truth    dunno  := FILE_NOT_FOUND;
const XmlTruth xdunno := fILE_NOT_FOUND;

const universal charstring estr_dunno :=    "<Truth>FILE_NOT_FOUND</Truth>\n\n";
const universal charstring estr_xdunno:= "<XmlTruth>FILE_NOT_FOUND</XmlTruth>\n\n";

testcase encode_truth() runs on Plain
{
  CHECK_METHOD(exer_enc_w,  dunno, estr_dunno);
  CHECK_METHOD(exer_enc_x, xdunno, estr_xdunno);
}

testcase decode_truth() runs on Plain
{
  CHECK_DECODE(exer_dec_w, estr_dunno,     Truth,  dunno);
  CHECK_DECODE(exer_dec_x, estr_xdunno, XmlTruth, xdunno);
}

/* * * * * * * * * * * * * * * * * * * * * * */
// Regression test for special escaped characters present in the text as variant

type record Special
{
  enumerated {
    numbers
  } expr
}
with {
  variant (expr) "text 'numbers' as '&lt;&gt;&quot;&amp;&apos;numbers&#60;&#62;&#34;&#38;&#39;'";
};

DECLARE_EXER_ENCODERS(Special, s);

const Special spec  := { expr := numbers };

const universal charstring estr_spec :=
  "<Special>\n\t<expr>&lt;&gt;&quot;&amp;&apos;numbers&#60;&#62;&#34;&#38;&#39;</expr>\n</Special>\n\n";

testcase encode_special() runs on Plain
{
  CHECK_METHOD(exer_enc_s,  spec, estr_spec);
}

testcase decode_special() runs on Plain
{
  CHECK_DECODE(exer_dec_s, estr_spec, Special, spec);
}

control
{
  execute(encode_txt());
  execute(decode_txt());

  execute(encode_semaphore());
  execute(decode_semaphore());

  execute(encode_cross());
  execute(decode_cross());
  
  execute(encode_truth());
  execute(decode_truth());

  execute(encode_special());
  execute(decode_special());
}


}
with {
encode "XML"

//"field qualifers..." error for:
// variant (ProductColorT.red) "text as uppercased"

}
