Commit 84ca6555 authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

Implemented OER coding: part1 (Bug 522222)



Change-Id: I554d0bc9773bdc68f78a31062839bfd8f01832d0
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent c8792d5d
......@@ -169,6 +169,8 @@ namespace Common {
return "TEXT";
case CT_JSON:
return "JSON";
case CT_OER:
return "OER";
case CT_CUSTOM:
return "custom";
default:
......@@ -187,6 +189,7 @@ namespace Common {
case CT_RAW:
case CT_XER: // UTF-8 doesn't fit into charstring and universal is wasteful
case CT_JSON:
case CT_OER:
return get_pooltype(T_OSTR);
case CT_TEXT:
if(stream_variant==1){
......@@ -605,6 +608,7 @@ namespace Common {
xerattrib = 0;
berattrib = 0;
jsonattrib = 0;
oerattrib = 0;
sub_type = 0;
parsed_restr = 0;
ownertype = OT_UNKNOWN;
......@@ -760,6 +764,8 @@ namespace Common {
berattrib = 0;
delete jsonattrib;
jsonattrib = 0;
delete oerattrib;
oerattrib = 0;
if (parsed_restr) {
for (size_t i = 0; i < parsed_restr->size(); i++)
delete (*parsed_restr)[i];
......@@ -3239,6 +3245,7 @@ namespace Common {
case CT_TEXT:
case CT_XER:
case CT_JSON:
case CT_OER:
break; // OK
default:
FATAL_ERROR("Type::set_gen_coder_functions");
......@@ -3466,7 +3473,8 @@ namespace Common {
(coding == CT_RAW && !enable_raw()) ||
(coding == CT_TEXT && !enable_text()) ||
(coding == CT_XER && !enable_xer()) ||
(coding == CT_JSON && !enable_json())) {
(coding == CT_JSON && !enable_json()) ||
(coding == CT_OER && !enable_oer())) {
return false;
}
......@@ -3596,6 +3604,16 @@ namespace Common {
return false;
}
case CT_OER:
switch (typetype) {
case T_BOOL:
case T_INT_A:
// TODO: add more types as they are implemented in
// the enc/decoding
return true;
default:
return false;
}
default:
FATAL_ERROR("Type::can_have_coding");
}
......@@ -5297,6 +5315,8 @@ namespace Common {
}
else if (enc == "PER")
return CT_PER;
else if (enc == "OER")
return CT_OER;
else
return CT_CUSTOM;
}
......@@ -6283,7 +6303,7 @@ namespace Common {
(encoding_type == CT_CUSTOM && custom_encoding == NULL)) {
FATAL_ERROR("Type::has_encoding");
}
if (!legacy_codec_handling && encoding_type != CT_BER && encoding_type != CT_PER) {
if (!legacy_codec_handling && encoding_type != CT_BER && encoding_type != CT_PER && encoding_type != CT_OER) {
// new codec handling (except for BER and PER, which work the same way as before)
// check the coding table
Type* t = get_type_w_coding_table();
......@@ -6750,6 +6770,28 @@ namespace Common {
} // else
} // while
} // case
case CT_OER: {
for ( ; ; ) {
if (t->is_asn1()) return true;
if (t->oerattrib) return true;
if (t->is_ref()) t = t->get_type_refd();
else {
switch (t->typetype) {
case T_ERROR:
case T_BOOL:
case T_INT:
case T_REAL:
case T_BSTR:
case T_OSTR:
case T_OID:
// these basic TTCN-3 types have ASN.1 equivalents
return true;
default:
return false;
}
}
}
}
case CT_CUSTOM:
// the encoding name parameter has to be the same as the encoding name
// specified for the type
......@@ -7204,7 +7246,8 @@ namespace Common {
*/
if (t->is_tagged() || t->rawattrib || t->textattrib || t->jsonattrib ||
(!t->is_asn1() && t->hasEncodeAttr(get_encoding_name(CT_JSON))) ||
(t->xerattrib && !t->xerattrib->empty() ))
(t->xerattrib && !t->xerattrib->empty() ) ||
(t->oerattrib && !t->oerattrib->empty() && t->is_asn1()))
{
return t->get_genname_own(p_scope);
}
......@@ -7394,6 +7437,17 @@ namespace Common {
}
return t->get_genname_typename(my_scope);
}
string Type::get_genname_oerdescriptor()
{
Type *t = this;
while (true) {
if (t->has_encoding(CT_OER)) return t->get_genname_own(my_scope);
else if (t->is_ref()) t = t->get_type_refd();
else break;
}
return t->get_genname_typename(my_scope);
}
const char* Type::get_genname_typedescr_asnbasetype()
{
......
......@@ -38,6 +38,7 @@
#include "ttcn3/TextAST.hh"
#include "ttcn3/BerAST.hh"
#include "ttcn3/JsonAST.hh"
#include "ttcn3/OerAST.hh"
#include <float.h>
class XerAttributes;
......@@ -209,6 +210,7 @@ namespace Common {
CT_UNDEF, /**< undefined/unused */
CT_BER, /**< ASN.1 BER (built-in) */
CT_PER, /**< ASN.1 PER (through user defined coder functions) */
CT_OER, /**< ASN.1 OER (built-in) */
CT_RAW, /**< TTCN-3 RAW (built-in) */
CT_TEXT, /**< TTCN-3 TEXT (built-in) */
CT_XER, /**< TTCN-3 XER (built-in) */
......@@ -361,6 +363,7 @@ namespace Common {
XerAttributes *xerattrib;
BerAST *berattrib;
JsonAST *jsonattrib;
OerAST *oerattrib;
vector<SubTypeParse> *parsed_restr; ///< parsed subtype restrictions are stored here until they are moved to the sub_type member
SubType *sub_type; ///< effective/aggregate subtype of this type, NULL if neither inherited nor own subtype restrictions exist
......@@ -910,6 +913,8 @@ namespace Common {
void chk_xer_use_order(int num_attributes);
void chk_xer_use_type();
void chk_xer_use_union();
void chk_oer();
bool is_root_basic();
int get_raw_length();
......@@ -1225,8 +1230,9 @@ namespace Common {
void generate_code_berdescriptor(output_struct *target);
void generate_code_rawdescriptor(output_struct *target);
void generate_code_textdescriptor(output_struct *target);
void generate_code_jsondescriptor(output_struct *target);
void generate_code_xerdescriptor(output_struct *target);
void generate_code_jsondescriptor(output_struct *target);
void generate_code_oerdescriptor(output_struct *target);
void generate_code_alias(output_struct *target);
void generate_code_Enum(output_struct *target);
void generate_code_Choice(output_struct *target);
......@@ -1351,6 +1357,7 @@ namespace Common {
string get_genname_textdescriptor();
string get_genname_xerdescriptor();
string get_genname_jsondescriptor();
string get_genname_oerdescriptor();
/** Return the ASN base type to be written into the type descriptor */
const char* get_genname_typedescr_asnbasetype();
/** parse subtype information and add parent's subtype information to
......
......@@ -201,6 +201,8 @@ void Type::chk()
chk_variants();
}
chk_oer();
chk_finished = true;
}
......@@ -826,10 +828,11 @@ void Type::chk_encodings()
case OT_RECORD_OF:
case OT_COMP_FIELD:
case OT_SELTYPE:
// ASN.1 types automatically have BER, PER, XER and JSON encoding
// ASN.1 types automatically have BER, PER, XER, OER and JSON encoding
add_coding(string("BER:2002"), Ttcn::MOD_NONE, true);
add_coding(string(get_encoding_name(CT_PER)), Ttcn::MOD_NONE, true);
add_coding(string(get_encoding_name(CT_JSON)), Ttcn::MOD_NONE, true);
add_coding(string(get_encoding_name(CT_OER)), Ttcn::MOD_NONE, true);
if (asn1_xer) {
// XER encoding for ASN.1 types can be disabled with a command line option
add_coding(string(get_encoding_name(CT_XER)), Ttcn::MOD_NONE, true);
......@@ -2972,6 +2975,65 @@ void Type::chk_xer() { // XERSTUFF semantic check
}
void Type::chk_oer() {
//if (!is_asn1()) return;
if (oerattrib == NULL) {
oerattrib = new OerAST();
}
switch (typetype) {
case T_BOOL:
break;
case T_INT_A: {
if (is_constrained()) {
Location loc;
int_limit_t upper = get_sub_type()->get_root()->get_int_limit(true, &loc);
int_limit_t lower = get_sub_type()->get_root()->get_int_limit(false, &loc);
bool lower_inf = lower.get_type() != int_limit_t::NUMBER;
bool upper_inf = upper.get_type() != int_limit_t::NUMBER;
if (lower_inf || upper_inf) {
oerattrib->signed_ = lower_inf;
oerattrib->bytes = -1;
} else {
int_val_t low = lower.get_value();
int_val_t up = upper.get_value();
if (low < 0) {
oerattrib->signed_ = true;
if (low >= -128 && up <= 127) {
oerattrib->bytes = 1;
} else if (low >= -32768 && up <= 32767) {
oerattrib->bytes = 2;
} else if (low >= -2147483648 && up <= 2147483647) {
oerattrib->bytes = 4;
} else if ((low+1) >= -9223372036854775807LL && up <= 9223372036854775807LL) {
oerattrib->bytes = 8;
} else {
oerattrib->bytes = -1;
}
} else {
static int_val_t uns_8_byte("18446744073709551615", NULL);
oerattrib->signed_ = false;
if (up <= 255) {
oerattrib->bytes = 1;
} else if (up <= 65535) {
oerattrib->bytes = 2;
} else if (up <= 4294967295) {
oerattrib->bytes = 4;
} else if (up <= uns_8_byte) {
oerattrib->bytes = 8;
} else {
oerattrib->bytes = -1;
}
}
}
} else {
oerattrib->signed_ = true;
oerattrib->bytes = -1;
}
break; }
default:
break;
}
}
void Type::chk_Int_A()
{
......
......@@ -279,7 +279,7 @@ void Type::generate_code_typedescriptor(output_struct *target)
// FIXME: force_xer should be elminated. if a type needs a descriptor,
// it should say so via get_genname_typedescriptor()
/* genname{type,ber,raw,text,xer,json}descriptor == gennameown is true if
/* genname{type,ber,raw,text,xer,json,oer}descriptor == gennameown is true if
* the type needs its own {type,ber,raw,text,xer,json}descriptor
* and can't use the descriptor of one of the built-in types.
*/
......@@ -319,6 +319,13 @@ void Type::generate_code_typedescriptor(output_struct *target)
if (generate_json && gennamejsondescriptor == gennameown) {
generate_code_jsondescriptor(target);
}
bool generate_oer = enable_oer() && (legacy_codec_handling ?
has_encoding(CT_OER) : last->get_gen_coder_functions(CT_OER));
const string& gennameoerdescriptor = get_genname_oerdescriptor();
if (generate_oer && gennameoerdescriptor == gennameown) {
generate_code_oerdescriptor(target);
}
// the type descriptor must be always exported.
// embedded (possibly unnamed) types can be referenced from other modules
......@@ -413,6 +420,13 @@ void Type::generate_code_typedescriptor(output_struct *target)
}
}
if (generate_oer)
target->source.global_vars = mputprintf(target->source.global_vars,
"&%s_oer_, ", gennamexerdescriptor.c_str());
else
target->source.global_vars = mputprintf(target->source.global_vars,
"NULL, ");
if (T_SEQOF == last->typetype || T_SETOF == last->typetype) {
target->source.global_vars=mputprintf(target->source.global_vars,
"&%s_descr_, ", get_type_refd_last()->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
......@@ -1066,6 +1080,25 @@ void Type::generate_code_jsondescriptor(output_struct *target)
}
void Type::generate_code_oerdescriptor(output_struct *target)
{
target->header.global_vars = mputprintf(target->header.global_vars,
"extern const TTCN_OERdescriptor_t %s_oer_;\n", get_genname_own().c_str());
if (NULL == oerattrib) {
target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE };\n"
, get_genname_own().c_str());
} else {
target->source.global_vars = mputprintf(target->source.global_vars,
"const TTCN_OERdescriptor_t %s_oer_ = { %i, %s };\n"
, get_genname_own().c_str()
, oerattrib->bytes
, oerattrib->signed_ ? "TRUE" : "FALSE");
}
}
void Type::generate_code_alias(output_struct *target)
{
if (!needs_alias()) return;
......@@ -1136,6 +1169,7 @@ void Type::generate_code_Enum(output_struct *target)
e_def.hasXer = legacy_codec_handling ? has_encoding(CT_XER) :
get_gen_coder_functions(CT_XER);
e_def.hasJson = get_gen_coder_functions(CT_JSON);
e_def.hasOer = get_gen_coder_functions(CT_OER);
if (xerattrib) {
e_def.xerUseNumber = xerattrib->useNumber_;
}
......@@ -1182,6 +1216,7 @@ void Type::generate_code_Choice(output_struct *target)
sdef.hasXer = legacy_codec_handling ? has_encoding(CT_XER) :
get_gen_coder_functions(CT_XER);
sdef.hasJson = get_gen_coder_functions(CT_JSON);
sdef.hasOer = get_gen_coder_functions(CT_OER);
sdef.has_opentypes = get_has_opentypes();
sdef.opentype_outermost = get_is_opentype_outermost();
sdef.ot = generate_code_ot(pool);
......@@ -1594,6 +1629,7 @@ void Type::generate_code_Se(output_struct *target)
sdef.hasXer = legacy_codec_handling ? has_encoding(CT_XER) :
get_gen_coder_functions(CT_XER);
sdef.hasJson = get_gen_coder_functions(CT_JSON);
sdef.hasOer = get_gen_coder_functions(CT_OER);
if (xerattrib){
Module *my_module = get_my_scope()->get_scope_mod();
sdef.xerHasNamespaces = my_module->get_nof_ns() != 0;
......@@ -2065,6 +2101,7 @@ void Type::generate_code_SeOf(output_struct *target)
sofdef.hasXer = legacy_codec_handling ? has_encoding(CT_XER) :
get_gen_coder_functions(CT_XER);
sofdef.hasJson = get_gen_coder_functions(CT_JSON);
sofdef.hasOer = get_gen_coder_functions(CT_OER);
if (xerattrib) {
//sofdef.xerList = xerattrib->list_;
sofdef.xerAttribute = xerattrib->attribute_;
......
......@@ -103,6 +103,7 @@ typedef struct {
boolean hasText;
boolean hasXer;
boolean hasJson;
boolean hasOer;
boolean xerUntagged;
boolean xerUntaggedOne; /**< from Type::u.secho.has_single_charenc */
boolean xerUseNilPossible; /* for sequence */
......@@ -137,6 +138,7 @@ typedef struct {
boolean hasText;
boolean hasXer;
boolean hasJson;
boolean hasOer;
/** true if this is a record-of BOOLEAN, ENUMERATED or NULL */
boolean xmlValueList;
/* * true if this record-of has the LIST encoding instruction */
......@@ -171,6 +173,7 @@ typedef struct {
boolean hasText;
boolean hasXer;
boolean hasJson;
boolean hasOer;
boolean xerUseNumber;
boolean xerText; /* A component has the TEXT encoding instruction */
size_t nElements;
......
......@@ -27,7 +27,7 @@
void def_encdec(const char *p_classname,
char **p_classdef, char **p_classsrc,
boolean ber, boolean raw, boolean text, boolean xer,
boolean json, boolean is_leaf)
boolean json, boolean oer, boolean is_leaf)
{
char *def=NULL;
char *src=NULL;
......
......@@ -34,12 +34,14 @@ extern "C" {
* @param[in] raw RAW codec needed
* @param[in] text TEXT codec needed
* @param[in] xer XER codec needed
* @param[in] json JSON codec needed
* @param[in] oer OER codec needed
* @param[in] is_leaf
* */
void def_encdec(const char *p_classname,
char **p_classdef, char **p_classsrc,
boolean ber, boolean raw, boolean text, boolean xer,
boolean json, boolean is_leaf);
boolean json, boolean oer, boolean is_leaf);
char *genRawFieldChecker(char *src,
const rawAST_coding_taglist *taglist, boolean is_equal);
char *genRawTagChecker(char *src, const rawAST_coding_taglist *taglist);
......
......@@ -43,6 +43,7 @@ void defEnumClass(const enum_def *edef, output_struct *output)
boolean text_needed= edef->hasText && enable_text();
boolean xer_needed = edef->hasXer && enable_xer();
boolean json_needed = edef->hasJson && enable_json();
boolean oer_needed = edef->hasOer && enable_oer();
char *enum_type, *qualified_enum_type, *unknown_value, *unbound_value;
enum_type = mcopystr("enum_type");
......@@ -442,9 +443,11 @@ void defEnumClass(const enum_def *edef, output_struct *output)
"}\n\n", name, enum_type, dispname);
/* BER functions */
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed,
raw_needed,text_needed, xer_needed, json_needed, TRUE);
raw_needed,text_needed, xer_needed, json_needed, oer_needed, TRUE);
}
if(ber_needed) {
src=mputprintf(src,
"ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
......
......@@ -233,6 +233,12 @@ boolean enable_json()
return !json_disabled;
}
boolean enable_oer()
{
// TODO: temp while no new compiler flag
return TRUE;
}
boolean disable_attribute_validation()
{
if (attribute_validation_disabled) return TRUE;
......
......@@ -62,6 +62,7 @@ extern boolean enable_per(void);
extern boolean enable_text(void);
extern boolean enable_xer(void);
extern boolean enable_json(void);
extern boolean enable_oer(void);
/**
* Checks whether the checking of encoding/decoding attributes is disabled.
......
......@@ -3200,6 +3200,7 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
boolean text_needed = sdef->hasText && enable_text();
boolean xer_needed = sdef->hasXer && enable_xer();
boolean json_needed = sdef->hasJson && enable_json();
boolean oer_needed = sdef->hasOer && enable_oer();
/* class declaration code */
output->header.class_decls = mputprintf(output->header.class_decls,
......@@ -3545,9 +3546,11 @@ void defRecordClass1(const struct_def *sdef, output_struct *output)
src = mputstr(src, "}\n\n");
/* The common "classname::encode()" and "classname::decode()" functions */
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed, raw_needed,
text_needed, xer_needed, json_needed, FALSE);
text_needed, xer_needed, json_needed, oer_needed, FALSE);
}
/* BER functions */
if(ber_needed) {
......@@ -5823,6 +5826,7 @@ static void defEmptyRecordClass(const struct_def *sdef,
boolean text_needed = sdef->hasText && enable_text();
boolean xer_needed = sdef->hasXer && enable_xer();
boolean json_needed = sdef->hasJson && enable_json();
boolean oer_needed = sdef->hasOer && enable_oer();
def = mputprintf(def,
#ifndef NDEBUG
......@@ -5960,9 +5964,11 @@ static void defEmptyRecordClass(const struct_def *sdef,
"bound_flag = TRUE;\n"
"}\n\n", name);
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed, raw_needed,
text_needed, xer_needed, json_needed, FALSE);
text_needed, xer_needed, json_needed, oer_needed, FALSE);
}
/* BER functions */
if(ber_needed) {
......
......@@ -60,6 +60,7 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
boolean oer_needed = force_gen_seof || (sdef->hasOer && enable_oer());
/* Class definition and private data members */
def = mputprintf(def,
......@@ -705,9 +706,11 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
"}\n"
"}\n\n", name, dispname, type, type);
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed,
xer_needed, json_needed, FALSE);
xer_needed, json_needed, oer_needed, FALSE);
}
if(text_needed){
src=mputprintf(src,
......@@ -1677,6 +1680,7 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
boolean text_needed = force_gen_seof || (sdef->hasText && enable_text());
boolean xer_needed = force_gen_seof || (sdef->hasXer && enable_xer());
boolean json_needed = force_gen_seof || (sdef->hasJson && enable_json());
boolean oer_needed = force_gen_seof || (sdef->hasOer && enable_oer());
/* Class definition and private data members */
def = mputprintf(def,
......@@ -2202,9 +2206,11 @@ void defRecordOfClassMemAllocOptimized(const struct_of_def *sdef, output_struct
"}\n"
"}\n\n", name, dispname, type);
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
if(ber_needed || raw_needed || text_needed || xer_needed || json_needed
|| oer_needed) {
def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed,
xer_needed, json_needed, FALSE);
xer_needed, json_needed, oer_needed, FALSE);
}
if (text_needed) {
src=mputprintf(src,
......
......@@ -7081,6 +7081,9 @@ namespace Ttcn {
case Type::CT_JSON:
if (enable_json()) return;
break;
case Type::CT_OER:
if (enable_oer()) return;
break;
case Type::CT_CUSTOM:
return; // cannot be disabled
default:
......
......@@ -666,7 +666,8 @@ namespace Ttcn {
(type->has_encoding(Type::CT_RAW)&&ti_type->has_encoding(Type::CT_RAW)) ||
(type->has_encoding(Type::CT_TEXT)&&ti_type->has_encoding(Type::CT_TEXT)) ||
(type->has_encoding(Type::CT_XER)&&ti_type->has_encoding(Type::CT_XER)) ||
(type->has_encoding(Type::CT_JSON)&&ti_type->has_encoding(Type::CT_JSON)))) {
(type->has_encoding(Type::CT_JSON)&&ti_type->has_encoding(Type::CT_JSON))) ||
(type->has_encoding(Type::CT_OER)&&ti_type->has_encoding(Type::CT_OER))) {
act_attr->error("Type `%s' and type `%s' have no common encoding",
ti_type->get_typename().c_str(), type->get_typename().c_str());
}
......
......@@ -54,7 +54,7 @@ GENERATED_OTHERS := compiler.output rawAST.output coding_attrib_p.output lex.bac
STATIC_SOURCES := ArrayDimensions.cc AST_ttcn3.cc Attributes.cc ILT.cc PatternString.cc \
RawAST.cc Statement.cc TtcnTemplate.cc Templatestuff.cc TextAST.cc Ttcnstuff.cc \
compiler.c port.c signature.c BerAST.cc JsonAST.cc Ttcn2Json.cc profiler.c
compiler.c port.c signature.c BerAST.cc JsonAST.cc Ttcn2Json.cc profiler.c OerAST.cc
SOURCES := $(STATIC_SOURCES) $(GENERATED_SOURCES)
......
/******************************************************************************
* Copyright (c) 2000-2017 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Szabo, Bence Janos
*
******************************************************************************/
#include "OerAST.hh"
OerAST::OerAST() :
bytes(0),
signed_(false)
{}
bool OerAST::empty() const {
return bytes == 0 && signed_ == false;
}
/******************************************************************************
* Copyright (c) 2000-2017 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Szabo, Bence Janos
*