diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc
index f972355ed45551dcaf1106f2d2a1730a7f2c7bcd..a496eb39f4dc72a0c0d07ea31ef8549ba7407bf1 100644
--- a/compiler2/ttcn3/Statement.cc
+++ b/compiler2/ttcn3/Statement.cc
@@ -1388,6 +1388,7 @@ namespace Ttcn {
       config_op.portref1=p_portref1;
       config_op.compref2=p_compref2;
       config_op.portref2=p_portref2;
+      config_op.translate=false;
       break;
     default:
       FATAL_ERROR("Statement::Statement()");
@@ -4738,24 +4739,24 @@ error:
       pt1 = chk_conn_endpoint(config_op.compref1, config_op.portref1, true);
       if (pt1) {
         ptb1 = pt1->get_PortBody();
-	if (ptb1->is_internal()) {
-	  config_op.portref1->warning("Port type `%s' was marked as `internal'",
-            pt1->get_typename().c_str());
-	}
+        if (ptb1->is_internal()) {
+          config_op.portref1->warning("Port type `%s' was marked as `internal'",
+                  pt1->get_typename().c_str());
+        }
       } else ptb1 = 0;
       Value *cref1 = config_op.compref1->get_value_refd_last();
       if (cref1->get_valuetype() == Value::V_EXPR) {
-	switch (cref1->get_optype()) {
-	case Value::OPTYPE_COMP_MTC:
-	case Value::OPTYPE_COMP_SELF:
-	case Value::OPTYPE_COMP_CREATE:
-	  cref1_is_tc = true;
-	  break;
-	case Value::OPTYPE_COMP_SYSTEM:
+        switch (cref1->get_optype()) {
+        case Value::OPTYPE_COMP_MTC:
+        case Value::OPTYPE_COMP_SELF:
+        case Value::OPTYPE_COMP_CREATE:
+	        cref1_is_tc = true;
+          break;
+        case Value::OPTYPE_COMP_SYSTEM:
           cref1_is_system = true;
-	default:
+        default:
           break;
-	}
+        }
       }
     }
     {
@@ -4764,23 +4765,23 @@ error:
       if (pt2) {
         ptb2 = pt2->get_PortBody();
         if (ptb2->is_internal()) {
-	  config_op.portref2->warning("Port type `%s' was marked as `internal'",
+          config_op.portref2->warning("Port type `%s' was marked as `internal'",
             pt2->get_typename().c_str());
-	}
+        }
       } else ptb2 = 0;
       Value *cref2 = config_op.compref2->get_value_refd_last();
       if (cref2->get_valuetype() == Value::V_EXPR) {
-	switch (cref2->get_optype()) {
-	case Value::OPTYPE_COMP_MTC:
-	case Value::OPTYPE_COMP_SELF:
-	case Value::OPTYPE_COMP_CREATE:
-	  cref2_is_tc = true;
-	  break;
-	case Value::OPTYPE_COMP_SYSTEM:
+        switch (cref2->get_optype()) {
+        case Value::OPTYPE_COMP_MTC:
+        case Value::OPTYPE_COMP_SELF:
+        case Value::OPTYPE_COMP_CREATE:
+	        cref2_is_tc = true;
+          break;
+        case Value::OPTYPE_COMP_SYSTEM:
           cref2_is_system = true;
-	default:
+        default:
           break;
-	}
+        }
       }
     }
     if (cref1_is_tc && cref2_is_tc) {
@@ -4794,24 +4795,30 @@ error:
     // checking consistency
     if (!ptb1 || !ptb2) return;
     if (cref1_is_tc || cref2_is_system) {
-      if (!ptb1->is_mappable(ptb2)) {
-	error("The mapping between test component port type `%s' and system "
-	  "port type `%s' is not consistent", pt1->get_typename().c_str(),
-	  pt2->get_typename().c_str());
-	ptb1->report_mapping_errors(ptb2);
+      // The check for safe mapping was already checked in
+      // PortTypeBody::chk_map_translation()
+      config_op.translate = !ptb1->is_legacy() && ptb1->is_translate(ptb2);
+      if (!config_op.translate && !ptb1->is_mappable(ptb2)) {
+        error("The mapping between test component port type `%s' and system "
+          "port type `%s' is not consistent", pt1->get_typename().c_str(),
+          pt2->get_typename().c_str());
+        ptb1->report_mapping_errors(ptb2);
       }
     } else if (cref2_is_tc || cref1_is_system) {
-      if (!ptb2->is_mappable(ptb1)) {
-	error("The mapping between system port type `%s' and test component "
-	  "port type `%s' is not consistent", pt1->get_typename().c_str(),
-	  pt2->get_typename().c_str());
-	ptb2->report_mapping_errors(ptb1);
+      config_op.translate = !ptb2->is_legacy() && ptb2->is_translate(ptb1);
+      if (!config_op.translate && !ptb2->is_mappable(ptb1)) {
+        error("The mapping between system port type `%s' and test component "
+          "port type `%s' is not consistent", pt1->get_typename().c_str(),
+          pt2->get_typename().c_str());
+        ptb2->report_mapping_errors(ptb1);
       }
     } else {
       // we have no idea which one is the system port
-      if (!ptb1->is_mappable(ptb1) && !ptb2->is_mappable(ptb1)) {
-	error("The mapping between port types `%s' and `%s' is not consistent",
-          pt1->get_typename().c_str(), pt2->get_typename().c_str());
+      config_op.translate = (!ptb1->is_legacy() && ptb1->is_translate(ptb2)) ||
+                            (!ptb2->is_legacy() && ptb2->is_translate(ptb1));
+      if (!config_op.translate && !ptb1->is_mappable(ptb1) && !ptb2->is_mappable(ptb1)) {
+        error("The mapping between port types `%s' and `%s' is not consistent",
+                pt1->get_typename().c_str(), pt2->get_typename().c_str());
       }
     }
   }
@@ -5536,33 +5543,33 @@ error:
       const Identifier& t_portid = *p_portref->get_id();
       if (!comp_body->has_local_ass_withId(t_portid)) {
         p_portref->error("Component type `%s' does not have port with name "
-	  "`%s'", comp_type->get_typename().c_str(),
-	  t_portid.get_dispname().c_str());
-	return 0;
+          "`%s'", comp_type->get_typename().c_str(),
+          t_portid.get_dispname().c_str());
+        return 0;
       }
       Common::Assignment *t_ass = comp_body->get_local_ass_byId(t_portid);
       if (t_ass->get_asstype() != Common::Assignment::A_PORT) {
-	p_portref->error("Definition `%s' in component type `%s' is a %s and "
-	  "not a port", t_portid.get_dispname().c_str(),
-	  comp_type->get_typename().c_str(), t_ass->get_assname());
-	return 0;
+        p_portref->error("Definition `%s' in component type `%s' is a %s and "
+          "not a port", t_portid.get_dispname().c_str(),
+          comp_type->get_typename().c_str(), t_ass->get_assname());
+        return 0;
       }
       ArrayDimensions *t_dims = t_ass->get_Dimensions();
       if (t_dims) t_dims->chk_indices(p_portref, "port", false,
-	Type::EXPECTED_DYNAMIC_VALUE);
+        Type::EXPECTED_DYNAMIC_VALUE);
       else if (p_portref->get_subrefs()) {
-	p_portref->error("Port `%s' is not an array. The "
-	  "reference cannot have array indices",
-	  t_portid.get_dispname().c_str());
+        p_portref->error("Port `%s' is not an array. The "
+          "reference cannot have array indices",
+          t_portid.get_dispname().c_str());
       }
       Type *port_type = t_ass->get_Type();
       if (port_type) {
-	// check whether the external interface is provided by another port type
-	PortTypeBody *port_body = port_type->get_PortBody();
-	if (port_body->get_type() == PortTypeBody::PT_USER) {
-	  Type *provider_type = port_body->get_provider_type();
-	  if (provider_type) port_type = provider_type;
-	}
+        // check whether the external interface is provided by another port type
+        PortTypeBody *port_body = port_type->get_PortBody();
+        if (port_body->get_type() == PortTypeBody::PT_USER && port_body->is_legacy()) {
+          Type *provider_type = port_body->get_provider_type();
+          if (provider_type) port_type = provider_type;
+        }
       }
       return port_type;
     } else {
@@ -5570,10 +5577,10 @@ error:
       FieldOrArrayRefs *t_subrefs = p_portref->get_subrefs();
       if (t_subrefs) {
         // check the array indices: they should be integers
-	for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
-	  t_subrefs->get_ref(i)->get_val()
-	    ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE);
-	}
+        for (size_t i = 0; i < t_subrefs->get_nof_refs(); i++) {
+          t_subrefs->get_ref(i)->get_val()
+            ->chk_expr_int(Type::EXPECTED_DYNAMIC_VALUE);
+        }
       }
       return 0;
     }
@@ -7374,7 +7381,29 @@ error:
       // a simple string shall be formed from the port name and array indices
       generate_code_portref(&expr, config_op.portref2);
     }
-    expr.expr = mputc(expr.expr, ')');
+    expr.expr = mputstr(expr.expr, ")");
+    if (config_op.translate) {
+      string funcname;
+      if (strcmp(opname, "map") == 0) {
+        funcname = "add_port";
+      } else if (strcmp(opname, "unmap") == 0) {
+        funcname = "remove_port";
+      } else {
+        //TODO connect, disconnect
+      }
+      if (!funcname.empty()) {
+        expr.expr = mputstr(expr.expr, ";\n");
+        config_op.portref1->generate_code_portref(&expr, my_sb);
+        expr.expr = mputprintf(expr.expr, ".%s(&(", funcname.c_str());
+        config_op.portref2->generate_code_portref(&expr, my_sb);
+        expr.expr = mputstr(expr.expr, "));\n");
+
+        config_op.portref2->generate_code_portref(&expr, my_sb);
+        expr.expr = mputprintf(expr.expr, ".%s(&(", funcname.c_str());
+        config_op.portref1->generate_code_portref(&expr, my_sb);
+        expr.expr = mputstr(expr.expr, "))");
+      }
+    }
     return Code::merge_free_expr(str, &expr);
   }
 
diff --git a/compiler2/ttcn3/Statement.hh b/compiler2/ttcn3/Statement.hh
index 5d27cb5cf8232cdb31a33029e081ba7aa0326992..dd67c6a5b76a9d4baa68db1bc59973ac4727ba8f 100644
--- a/compiler2/ttcn3/Statement.hh
+++ b/compiler2/ttcn3/Statement.hh
@@ -342,6 +342,7 @@ namespace Ttcn {
         Reference *portref1;
         Value *compref2;
         Reference *portref2;
+        bool translate; // true if a map statement enables translation mode
       } config_op; ///< used by S_CONNECT, S_MAP, S_DISCONNECT, S_UNMAP
 
       struct {
diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc
index aa26b3bce08a74d472477b6db2213425831be519..df63013b3c257a01984f07b801b6c3eac9fa36d2 100644
--- a/compiler2/ttcn3/Ttcnstuff.cc
+++ b/compiler2/ttcn3/Ttcnstuff.cc
@@ -1028,7 +1028,8 @@ namespace Ttcn {
     checked(false), legacy(true),
     in_msgs(0), out_msgs(0), in_sigs(0), out_sigs(0),
     testport_type(TP_REGULAR), port_type(PT_REGULAR),
-    provider_refs(), provider_types(), in_mappings(0), out_mappings(0)
+    provider_refs(), provider_types(), mapper_types(),
+    in_mappings(0), out_mappings(0)
   {
   }
 
@@ -1046,6 +1047,7 @@ namespace Ttcn {
     }
     provider_refs.clear();
     provider_types.clear();
+    mapper_types.clear();
     delete in_mappings;
     delete out_mappings;
   }
@@ -1232,7 +1234,7 @@ namespace Ttcn {
   {
     if (!checked || port_type != PT_USER)
       FATAL_ERROR("PortTypeBody::get_provider_type()");
-    return provider_types[0]; // TODO, called in check coonn endpoint
+    return provider_types[0];
   }
 
   void PortTypeBody::chk_list(const Types *list, bool is_in, bool is_out)
@@ -1338,8 +1340,6 @@ namespace Ttcn {
       FATAL_ERROR("PortTypeBody::chk_map_translation()");
     }
     
-    vector<Type> provider_ins;
-    
     TypeSet mapping_ins;
     
     if (in_mappings) {
@@ -1357,63 +1357,45 @@ namespace Ttcn {
       PortTypeBody *provider_body = provider_types[i]->get_PortBody();
       if (provider_body->in_msgs) {
         for (size_t j = 0; j < provider_body->in_msgs->get_nof_types(); j++) {
-          provider_ins.add(provider_body->in_msgs->get_type_byIndex(j));
-        }
-      }
-
-      for (size_t j = 0; j < provider_ins.size(); j++) {
-        bool found = false;
-        if (inout_list) {
-          for (size_t k = 0; k < inout_list->get_nof_types(); k++) {
-            if (provider_ins[j]->get_typename() == inout_list->get_type_byIndex(k)->get_typename()) {
-              found = true;
-              break;
+          bool found = false;
+          if (inout_list) {
+            for (size_t k = 0; k < inout_list->get_nof_types(); k++) {
+              if (provider_body->in_msgs->has_type(inout_list->get_type_byIndex(k))) {
+                found = true;
+                break;
+              }
             }
           }
+          if (((in_msgs && in_msgs->has_type(provider_body->in_msgs->get_type_byIndex(j))) // Provider in message is present in the port in message
+              || mapping_ins.has_type(provider_body->in_msgs->get_type_byIndex(j)) // Provider in message is present in one of the in mappings
+              || found // Provider in message is present in the inout list of the port 
+              ) == false) {
+            error("Incoming message type `%s' is not present in the in(out) message list or in the from mapping types, coming from port: `%s'.",
+              provider_body->in_msgs->get_type_byIndex(j)->get_typename().c_str(),
+              provider_types[i]->get_dispname().c_str());
+          }
         }
-        if (((in_msgs && in_msgs->has_type(provider_ins[j])) // Provider in message is present in the port in message
-            || mapping_ins.has_type(provider_ins[j]) // Provider in message is present in one of the in mappings
-            || found // Provider in message is present in the inout list of the port 
-            ) == false) {
-          error("Incoming message type `%s' is not present in the in(out) message list or in the from mapping types, coming from port: `%s'.",
-            provider_ins[j]->get_typename().c_str(),
-            provider_types[i]->get_dispname().c_str()); // in mapping snull
-        }
-      }
+      } // if provider_body->in_msgs
       
       if (inout_list) {
         for (size_t j = 0; j < inout_list->get_nof_types(); j++) {
-          if (provider_body->inout_list) {
-            bool found = false;
-            // If the inout message of the port is present on the provider inout message list
-            for (size_t k = 0; k < provider_body->inout_list->get_nof_types(); k++) {
-              if (inout_list->get_type_byIndex(j)->get_typename() ==
-                  provider_body->inout_list->get_type_byIndex(k)->get_typename()) {
-                found = true;
-                break;
-              }
-            }
-            if (found) {
-              continue;
-            }
-          }
           bool found_in = false;
-          if (provider_body->in_list) {
+          if (provider_body->in_msgs) {
             // If the inout message of the port is present on the provider in message list
-            for (size_t k = 0; k < provider_body->in_list->get_nof_types(); k++) {
+            for (size_t k = 0; k < provider_body->in_msgs->get_nof_types(); k++) {
               if (inout_list->get_type_byIndex(j)->get_typename() ==
-                  provider_body->in_list->get_type_byIndex(k)->get_typename()) {
+                  provider_body->in_msgs->get_type_byIndex(k)->get_typename()) {
                 found_in = true;
                 break;
               }
             }
           }
           bool found_out = false;
-          if (provider_body->out_list) {
+          if (provider_body->out_msgs) {
             // If the inout message of the port is present on the provider out message list
-            for (size_t k = 0; k < provider_body->out_list->get_nof_types(); k++) {
+            for (size_t k = 0; k < provider_body->out_msgs->get_nof_types(); k++) {
               if (inout_list->get_type_byIndex(j)->get_typename() ==
-                  provider_body->out_list->get_type_byIndex(k)->get_typename()) {
+                  provider_body->out_msgs->get_type_byIndex(k)->get_typename()) {
                 found_out = true;
                 break;
               }
@@ -1427,29 +1409,44 @@ namespace Ttcn {
               provider_types[i]->get_dispname().c_str());
           }
         }
-      }
+      } // if inout_list
       
       if (out_list) {
         for (size_t j = 0; j < out_list->get_nof_types(); j++) {
           bool found = false;
-          if (provider_body->out_list) {
-            for (size_t k = 0; k < provider_body->out_list->get_nof_types(); k++) {
-              if (out_list->get_type_byIndex(j)->get_typename() ==
-                  provider_body->out_list->get_type_byIndex(k)->get_typename()) {
+          if (provider_body->out_msgs) {
+            for (size_t k = 0; k < provider_body->out_msgs->get_nof_types(); k++) {
+              if (out_msgs->has_type(provider_body->out_msgs->get_type_byIndex(k))) {
                 found = true;
                 break;
               }
             }
           }
+          
+          // Check if the port's out message list contains at least one of the 
+          // type's target mappings.
           if (!found) {
-            error("Out message type `%s' is not present in the out message list of the port `%s'.",
+            if (out_mappings->has_mapping_for_type(out_msgs->get_type_byIndex(j))) {
+              TypeMapping* type_mapping = out_mappings->get_mapping_byType(out_msgs->get_type_byIndex(j));
+              for (size_t k = 0; k < type_mapping->get_nof_targets(); k++) {
+                if (provider_body->out_msgs->has_type(type_mapping->get_target_byIndex(k)->get_target_type())) {
+                  found = true;
+                  break;
+                }
+              }
+            }
+          }
+          
+          if (!found) {
+            error("Neither out message type `%s', nor one of its target"
+              "mappings are present in the out or inout message list of the port `%s'.",
+              out_list->get_type_byIndex(j)->get_typename().c_str(),
               out_list->get_type_byIndex(j)->get_typename().c_str(),
               provider_types[i]->get_dispname().c_str());
           }
         }
-      }
-      provider_ins.clear();
-    } // provider_types.size()
+      } // if out_list
+    } // for provider_types.size()
   }
   
   void PortTypeBody::chk_connect_translation() {
@@ -1471,9 +1468,24 @@ namespace Ttcn {
         if (t_ass->get_asstype() == Assignment::A_TYPE) {
           Type *t = t_ass->get_Type()->get_type_refd_last();
           if (t->get_typetype() == Type::T_PORT) {
-            provider_types.add(t);
-            n_prov_t++;
-            provider_body = t->get_PortBody();
+            bool found = false;
+            // Provider types can only be given once.
+            for (size_t i = 0; i < provider_types.size(); i++) {
+              if (provider_types[i] == t) {
+                found = true;
+                my_type->error("Duplicate port mappings, the type `%s' appears more than once.",
+                  t->get_dispname().c_str());
+                break;
+              }
+            }
+            if (!found) {
+              provider_types.add(t);
+              n_prov_t++;
+              provider_body = t->get_PortBody();
+              if (!legacy) {
+                provider_body->add_mapper_type(my_type);
+              }
+            }
           } else {
             provider_refs[p]->error("Type reference `%s' does not refer to a port "
               "type", provider_refs[p]->get_dispname().c_str());
@@ -1910,6 +1922,15 @@ namespace Ttcn {
       }
     }
   }
+  
+  bool PortTypeBody::is_translate(PortTypeBody *p_other) const {
+    for (size_t i = 0; i < provider_types.size(); i++) {
+      if (provider_types[i]->get_fullname() == p_other->get_my_type()->get_fullname()) {
+        return true;
+      }
+    }
+    return false;
+  }
 
   bool PortTypeBody::is_mappable(PortTypeBody *p_other) const
   {
@@ -2149,8 +2170,12 @@ namespace Ttcn {
       pdef.port_type = USER;
       if (provider_types.size() == 0) FATAL_ERROR("PortTypeBody::generate_code()");
       if (legacy) {
-        pdef.provider_name =
-          pool.add(provider_types[0]->get_genname_value(my_scope));
+        pdef.provider_msg_outlist.nElements = 1;
+        pdef.provider_msg_outlist.elements = (port_msg_prov*)Malloc(sizeof(*pdef.provider_msg_outlist.elements));
+        pdef.provider_msg_outlist.elements[0].name =
+           pool.add(provider_types[0]->get_genname_value(my_scope));
+        pdef.provider_msg_outlist.elements[0].n_out_msg_type_names = 0;
+        pdef.provider_msg_outlist.elements[0].out_msg_type_names = NULL;
         PortTypeBody *provider_body = provider_types[0]->get_PortBody();
         if (provider_body->in_msgs) {
           if (!in_mappings) // !this->in_msgs OK for an all-discard mapping
@@ -2193,7 +2218,26 @@ namespace Ttcn {
           pdef.provider_msg_in.elements = NULL;
         }
       } else { // non-legacy standard like behaviour
-        pdef.provider_name = 0; // For non legacy generation it is not needed
+        // Collect the out message lists of the provider ports along with the
+        // name of the provider port type
+        pdef.provider_msg_outlist.nElements = provider_types.size();
+        pdef.provider_msg_outlist.elements = (port_msg_prov*)Malloc(provider_types.size() * sizeof(*pdef.provider_msg_outlist.elements));
+        for (size_t i = 0; i < pdef.provider_msg_outlist.nElements; i++) {
+          port_msg_prov * msg_prov = pdef.provider_msg_outlist.elements + i;
+          msg_prov->name = pool.add(provider_types[i]->get_genname_value(my_scope));
+          PortTypeBody * ptb = provider_types[i]->get_PortBody();
+          if (ptb->out_msgs) {
+            // Collect out message list type names
+            msg_prov->n_out_msg_type_names = ptb->out_msgs->get_nof_types();
+            msg_prov->out_msg_type_names = (const char**)Malloc(msg_prov->n_out_msg_type_names * sizeof(*msg_prov->out_msg_type_names));
+            for (size_t j = 0; j < msg_prov->n_out_msg_type_names; j++) {
+              msg_prov->out_msg_type_names[j] = pool.add(ptb->out_msgs->get_type_byIndex(j)->get_genname_value(my_scope));
+            }
+          } else {
+            msg_prov->n_out_msg_type_names = 0;
+            msg_prov->out_msg_type_names = NULL;
+          }
+        }
         pdef.provider_msg_in.nElements = 0;
         pdef.provider_msg_in.elements = NULL;
         if (in_msgs) {
@@ -2274,10 +2318,19 @@ namespace Ttcn {
       if (port_type == PT_PROVIDER && testport_type != TP_INTERNAL)
         pdef.port_type = PROVIDER;
       else pdef.port_type = REGULAR;
-      pdef.provider_name = NULL;
+      pdef.provider_msg_outlist.nElements = 0;
+      pdef.provider_msg_outlist.elements = NULL;
       pdef.provider_msg_in.nElements = 0;
       pdef.provider_msg_in.elements = NULL;
     }
+    
+    if (port_type == PT_PROVIDER) {
+      pdef.mapper_name = (const char**)Malloc(mapper_types.size() * sizeof(const char*));
+      pdef.n_mapper_name = mapper_types.size();
+      for (size_t i = 0; i < mapper_types.size(); i++) {
+        pdef.mapper_name[i] = pool.add(mapper_types[i]->get_genname_value(my_scope));
+      }
+    }
 
     defPortClass(&pdef, target);
     if (generate_skeleton && testport_type != TP_INTERNAL &&
@@ -2292,6 +2345,10 @@ namespace Ttcn {
     for (size_t i = 0; i < pdef.provider_msg_in.nElements; i++)
       Free(pdef.provider_msg_in.elements[i].targets);
     Free(pdef.provider_msg_in.elements);
+    for (size_t i = 0; i < pdef.provider_msg_outlist.nElements; i++)
+      Free(pdef.provider_msg_outlist.elements[i].out_msg_type_names);
+    Free(pdef.provider_msg_outlist.elements);
+    Free(pdef.mapper_name);
   }
 
   void PortTypeBody::dump(unsigned level) const
diff --git a/compiler2/ttcn3/Ttcnstuff.hh b/compiler2/ttcn3/Ttcnstuff.hh
index dab0d4cdec528b81c3d8709e48d3b2d237c66e4e..3b02f2e5f9519f83b48dc3b7d2fb21c4c5ae7420 100644
--- a/compiler2/ttcn3/Ttcnstuff.hh
+++ b/compiler2/ttcn3/Ttcnstuff.hh
@@ -400,7 +400,9 @@ private:
   TestPortAPI_t testport_type; // regular|internal|address
   PortType_t port_type; // regular|provider|user
   vector<Ttcn::Reference>provider_refs; ///< references to provider ports, for PT_USER
-  vector<Common::Type> provider_types; ///< the types that provider_refs refers to
+  vector<Common::Type> provider_types; ///< the types that provider_refs refers to, for PT_USER
+  vector<Common::Type> mapper_types; ///< the types that map this port.
+                                     ///< only for PT_USER && !legacy
   TypeMappings *in_mappings, *out_mappings; ///< mappings for PT_USER
   /** Copy constructor not implemented */
   PortTypeBody(const PortTypeBody& p);
@@ -458,6 +460,11 @@ public:
    * test component port to system port \a p_other.
    * Applicable only if \a is_mappable() returned false. */
   void report_mapping_errors(PortTypeBody *p_other) const;
+  /** True if the PortTypeBody has translation capability towards p_other */
+  bool is_translate(PortTypeBody *p_other) const;
+  Type* get_my_type() const { return my_type; }
+  bool is_legacy() const { return legacy; }
+  void add_mapper_type(Type* t) { mapper_types.add(t); }
   void generate_code(output_struct *target);
   virtual void dump(unsigned level) const;
 };
diff --git a/compiler2/ttcn3/port.c b/compiler2/ttcn3/port.c
index 2391790b7eed5e704a836dde45f6e2e16c3a58b5..b762ae6b106f5a6a2ec47ebed095254983e72db2 100644
--- a/compiler2/ttcn3/port.c
+++ b/compiler2/ttcn3/port.c
@@ -69,6 +69,19 @@ static char *generate_send_mapping(char *src, const port_def *pdef,
       src = mputstr(src, "TTCN_Buffer ttcn_buffer(send_par);\n");
       /* has_buffer will be set to TRUE later */
     }
+    if (!pdef->legacy && pdef->port_type == USER) {
+      // Mappings should only happen if the port it is mapped to has the same
+      // outgoing message type as the mapping target.
+      src = mputstr(src, "if (false");
+      for (size_t j = 0; j < pdef->provider_msg_outlist.nElements; j++) {
+        for (size_t k = 0; k < pdef->provider_msg_outlist.elements[j].n_out_msg_type_names; k++) {
+          if (strcmp(target->target_name, pdef->provider_msg_outlist.elements[j].out_msg_type_names[k]) == 0) {
+            src = mputprintf(src, " || p_%i != NULL", (int)j);
+          }
+        }
+      }
+      src = mputstr(src, ") {\n");
+    }
     if (mapped_type->nTargets > 1) src = mputstr(src, "{\n");
     switch (target->mapping_type) {
     case M_FUNCTION:
@@ -164,8 +177,10 @@ static char *generate_send_mapping(char *src, const port_def *pdef,
     } else {
       if (pdef->testport_type != INTERNAL) {
         src = mputprintf(src, "if (destination_component == "
-          "SYSTEM_COMPREF) outgoing_send(mapped_par%s);\n"
-          "else {\n", pdef->testport_type == ADDRESS ? ", NULL" : "");
+          "SYSTEM_COMPREF) outgoing_%ssend(mapped_par%s);\n"
+          "else {\n",
+          pdef->port_type == USER && !pdef->legacy ? "mapped_" : "",
+          pdef->testport_type == ADDRESS ? ", NULL" : "");
       }
       src = mputprintf(src, "Text_Buf text_buf;\n"
         "prepare_message(text_buf, \"%s\");\n"
@@ -185,6 +200,10 @@ static char *generate_send_mapping(char *src, const port_def *pdef,
       src = mputstr(src, "}\n");
     }
     if (mapped_type->nTargets > 1) src = mputstr(src, "}\n");
+    if (!pdef->legacy && pdef->port_type == USER) {
+      // end of the outgoing messages of port with mapping target check
+      src = mputstr(src, "}\n");
+    }
   }
   if (has_discard) {
     if (mapped_type->nTargets > 1) {
@@ -1392,7 +1411,8 @@ void defPortClass(const port_def* pdef, output_struct* output)
     case USER:
       if (pdef->legacy) {
         class_name = mcopystr(pdef->name);
-        base_class_name = mprintf("%s_PROVIDER", pdef->provider_name);
+        // legacy always has one provider_name
+        base_class_name = mprintf("%s_PROVIDER", pdef->provider_msg_outlist.elements[0].name);
         break;
       }
       // else fall through
@@ -1605,6 +1625,21 @@ void defPortClass(const port_def* pdef, output_struct* output)
     src = mputstr(src, "}\n\n");
   }
   
+  // Port variables which can be the mapped ports for translation
+  if (pdef->port_type == USER && !pdef->legacy) {
+    def = mputstr(def, "private:\n");
+    for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) {
+      def = mputprintf(def, "%s* p_%i;\n", pdef->provider_msg_outlist.elements[i].name, (int)i);
+    }
+  }
+  
+  // Port variables which can be the mapper ports for translation
+  if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+    def = mputstr(def, "private:\n");
+    for (i = 0; i < pdef->n_mapper_name; i++) {
+      def = mputprintf(def, "%s* p_%i;\n", pdef->mapper_name[i], (int)i);
+    }
+  }
   
   def = mputstr(def, "public:\n");
 
@@ -1625,6 +1660,16 @@ void defPortClass(const port_def* pdef, output_struct* output)
     "msg_queue_tail = NULL;\n");
   if (has_proc_queue) src = mputstr(src, "proc_queue_head = NULL;\n"
     "proc_queue_tail = NULL;\n");
+  if (pdef->port_type == USER && !pdef->legacy) {
+    for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) {
+      src = mputprintf(src, "p_%i = NULL;\n", (int)i);
+    }
+  }
+  if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+    for (i = 0; i < pdef->n_mapper_name; i++) {
+      src = mputprintf(src, "p_%i = NULL;\n", (int)i);
+    }
+  }
   src = mputstr(src, "}\n\n");
 
   /* destructor */
@@ -1660,7 +1705,11 @@ void defPortClass(const port_def* pdef, output_struct* output)
       "send_par.log(), TTCN_Logger::end_event_log2str()));\n"
       "}\n", class_name, msg->name, msg->dispname);
     if (pdef->port_type != USER || (msg->nTargets == 1 &&
-      msg->targets[0].mapping_type == M_SIMPLE)) {
+      msg->targets[0].mapping_type == M_SIMPLE) || (pdef->port_type == USER && !pdef->legacy)) {
+      // If not in translation mode then send message as normally would.
+      if (pdef->port_type == USER && !pdef->legacy && msg->nTargets > 1) {
+        src = mputstr(src, "if (!in_translation_mode()) {\n");
+      }
       /* the same message type goes through the external interface */
       src = mputstr(src, "if (destination_component == SYSTEM_COMPREF) ");
       if (pdef->testport_type == INTERNAL) {
@@ -1671,8 +1720,9 @@ void defPortClass(const port_def* pdef, output_struct* output)
           "{\n"
           // To generate DTE-s if not mapped or connected.
           "(void)get_default_destination();\n"
-          "outgoing_send(send_par%s);\n"
+          "outgoing_%ssend(send_par%s);\n"
           "}\n",
+          pdef->port_type == USER && !pdef->legacy ? "mapped_" : "",
           pdef->testport_type == ADDRESS ? ", NULL" : "");
       }
       src = mputprintf(src, "else {\n"
@@ -1681,6 +1731,13 @@ void defPortClass(const port_def* pdef, output_struct* output)
         "send_par.encode_text(text_buf);\n"
         "send_data(text_buf, destination_component);\n"
         "}\n", msg->dispname);
+      if (pdef->port_type == USER && !pdef->legacy && msg->nTargets > 1) {
+        // If in translation mode then generate the send mappings and send
+        // according to them.
+        src = mputstr(src, "} else {\n");
+        src = generate_send_mapping(src, pdef, msg, FALSE);
+        src = mputstr(src, "}\n");
+      }
     } else {
       /* the message type is mapped to another outgoing type of the
        * external interface */
@@ -1985,19 +2042,72 @@ void defPortClass(const port_def* pdef, output_struct* output)
       "}\n\n", class_name, sig->name);
   }
 
+    
+  if (pdef->port_type == USER && !pdef->legacy) {
+    def = mputstr(def, "public:\n");
+    // add_port and remove_port is called after the map and unmap statements.
+    for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) {
+      def = mputprintf(def, "void add_port(%s* p);\n", pdef->provider_msg_outlist.elements[i].name);
+      src = mputprintf(src, "void %s::add_port(%s*p) {\n p_%i = p;\n}\n\n", class_name, pdef->provider_msg_outlist.elements[i].name, (int)i);
+      
+      def = mputprintf(def, "void remove_port(%s*);\n", pdef->provider_msg_outlist.elements[i].name);
+      src = mputprintf(src, "void %s::remove_port(%s*) {\n p_%i = NULL;\n}\n\n", class_name, pdef->provider_msg_outlist.elements[i].name, (int)i);
+    }
+    
+    // in_translation_mode returns true if one of the port variables are not null
+    def = mputstr(def, "boolean in_translation_mode() const;\n");
+    src = mputprintf(src, "boolean %s::in_translation_mode() const {\nreturn ", class_name);
+    for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) {
+      src = mputprintf(src, "p_%i != NULL %s",
+        (int)i,
+        i != pdef->provider_msg_outlist.nElements - 1 ? "|| " : "");
+    }
+    src = mputstr(src, ";\n}\n\n");
+    
+    def = mputstr(def, "private:\n");
+    // Resets all port variables to NULL
+    def = mputstr(def, "void reset_port_variables();\n");
+    src = mputprintf(src, "void %s::reset_port_variables() {\n", class_name);
+    for (i = 0; i < pdef->provider_msg_outlist.nElements; i++) {
+      src = mputprintf(src, "p_%i = NULL;\n", (int)i);
+    }
+    src = mputstr(src, "}\n\n");
+  }
+  
+  if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+    def = mputstr(def, "public:\n");
+    // add_port and remove_port is called after the map and unmap statements.
+    for (i = 0; i < pdef->n_mapper_name; i++) {
+      def = mputprintf(def, "void add_port(%s* p);\n", pdef->mapper_name[i]);
+      src = mputprintf(src, "void %s::add_port(%s*p) {\n p_%i = p;\n}\n\n", class_name, pdef->mapper_name[i], (int)i);
+      
+      def = mputprintf(def, "void remove_port(%s*);\n", pdef->mapper_name[i]);
+      src = mputprintf(src, "void %s::remove_port(%s*) {\n p_%i = NULL;\n}\n\n", class_name, pdef->mapper_name[i], (int)i);
+    }
+    def = mputstr(def, "private:\n");
+    // Resets all port variables to NULL
+    def = mputstr(def, "void reset_port_variables();\n");
+    src = mputprintf(src, "void %s::reset_port_variables() {\n", class_name);
+    for (i = 0; i < pdef->n_mapper_name; i++) {
+      src = mputprintf(src, "p_%i = NULL;\n", (int)i);
+    }
+    src = mputstr(src, "}\n\n");
+  }
+  
   if (pdef->testport_type != INTERNAL &&
      (pdef->port_type == REGULAR || (pdef->port_type == USER && !pdef->legacy))) {
     /* virtual functions for transmission (implemented by the test port) */
-    def = mputstr(def, "protected:\n");
+    def = mputprintf(def, "%s:\n",
+      (pdef->port_type == USER && !pdef->legacy) ? "public" : "protected");
     /* outgoing_send functions */
     size_t n_used = 0;
     const char** used = NULL;
     // Only print one outgoing_send for each type
     for (i = 0; i < pdef->msg_out.nElements; i++) {
-      used = (const char**)Realloc(used, (n_used + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*));
+      used = (const char**)Realloc(used, (n_used + 1) * sizeof(const char*));
       boolean found = FALSE;
-      for (size_t k = 0; k < n_used; k++) {
-        if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) {
+      for (size_t j = 0; j < n_used; j++) {
+        if (strcmp(used[j], pdef->msg_out.elements[i].name) == 0) {
           found = TRUE;
           break;
         }
@@ -2010,12 +2120,61 @@ void defPortClass(const port_def* pdef, output_struct* output)
             pdef->address_name);
         }
         def = mputstr(def, ") = 0;\n");
+        // When port translation is enabled
+        // we call the outgoing_mapped_send instead of outgoing_send,
+        // and this function will call one of the mapped port's outgoing_send
+        // functions, or its own outgoing_send function.
+        // This is for the types that are present in the out message list of the port
+        if (pdef->port_type == USER && !pdef->legacy) {
+          def = mputprintf(def, "void outgoing_mapped_send("
+          "const %s& send_par);\n", pdef->msg_out.elements[i].name);
+        
+          src = mputprintf(src, "void %s::outgoing_mapped_send("
+            "const %s& send_par", class_name, pdef->msg_out.elements[i].name);
+          if (pdef->testport_type == ADDRESS) {
+            def = mputprintf(def, ", const %s *destination_address",
+              pdef->address_name);
+          }
+          src = mputstr(src, ") {\n");
+          for (size_t j = 0; j < pdef->provider_msg_outlist.nElements; j++) {
+            found = FALSE;
+            for (size_t k = 0; k < pdef->provider_msg_outlist.elements[j].n_out_msg_type_names; k++) {
+              if (strcmp(pdef->msg_out.elements[i].name, pdef->provider_msg_outlist.elements[j].out_msg_type_names[k]) == 0) {
+                found = TRUE;
+                break;
+              }
+            }
+            if (found) {
+              src = mputprintf(src,
+                "if (p_%i != NULL) {\n"
+                "p_%i->outgoing_send(send_par);\n"
+                "return;\n}\n", (int)j, (int)j);
+            }
+          }
+          found = FALSE;
+          for (size_t j = 0; j < pdef->msg_out.nElements; j++) {
+            if (strcmp(pdef->msg_out.elements[j].name, pdef->msg_out.elements[i].name) == 0) {
+              found = TRUE;
+              break;
+            }
+          }
+          if (found) {
+            src = mputprintf(src, "outgoing_send(send_par);\n");
+          } else {
+            src = mputprintf(src, "TTCN_error(\"Cannot send this correctly %s\");\n", pdef->msg_out.elements[i].name); // todo
+          }
+          src = mputstr(src, "}\n\n");
+        }
         used[n_used] = pdef->msg_out.elements[i].name;
         n_used++;
       }
-      if (pdef->port_type == USER && !pdef->legacy) {
+    }
+    
+    if (pdef->port_type == USER && !pdef->legacy) {
+      for (i = 0; i < pdef->msg_out.nElements; i++) {
         for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) {
-          found = FALSE;
+          boolean found = FALSE;
+          used = (const char**)Realloc(used, (n_used + 1) * sizeof(const char*));
           for (size_t k = 0; k < n_used; k++) {
             if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) {
               found = TRUE;
@@ -2023,13 +2182,50 @@ void defPortClass(const port_def* pdef, output_struct* output)
             }
           }
           if (!found) {
-            def = mputprintf(def, "virtual void outgoing_send("
-              "const %s& send_par", pdef->msg_out.elements[i].targets[j].target_name);
+            // When standard like port translated port is present,
+            // We call the outgoing_mapped_send instead of outgoing_send,
+            // and this function will call one of the mapped port's outgoing_send
+            // functions, or its own outgoing_send function.
+            // This is for the mapping target types.
+            def = mputprintf(def, "void outgoing_mapped_send("
+            "const %s& send_par);\n", pdef->msg_out.elements[i].targets[j].target_name);
+
+            src = mputprintf(src, "void %s::outgoing_mapped_send("
+              "const %s& send_par", class_name, pdef->msg_out.elements[i].targets[j].target_name);
             if (pdef->testport_type == ADDRESS) {
               def = mputprintf(def, ", const %s *destination_address",
                 pdef->address_name);
             }
-            def = mputstr(def, ") = 0;\n");
+            src = mputstr(src, ") {\n");
+            for (size_t k = 0; k < pdef->provider_msg_outlist.nElements; k++) {
+              found = FALSE;
+              for (size_t l = 0; l < pdef->provider_msg_outlist.elements[k].n_out_msg_type_names; l++) {
+                if (strcmp(pdef->msg_out.elements[i].targets[j].target_name, pdef->provider_msg_outlist.elements[k].out_msg_type_names[l]) == 0) {
+                  found = TRUE;
+                  break;
+                }
+              }
+              if (found) {
+                src = mputprintf(src,
+                  "if (p_%i != NULL) {\n"
+                  "p_%i->outgoing_send(send_par);\n"
+                  "return;\n}\n", (int)k, (int)k);
+              }
+            }
+            found = FALSE;
+            for (size_t k = 0; k < pdef->msg_out.nElements; k++) {
+              if (strcmp(pdef->msg_out.elements[k].name, pdef->msg_out.elements[i].targets[j].target_name) == 0) {
+                found = TRUE;
+                break;
+              }
+            }
+            if (found) {
+              src = mputprintf(src, "outgoing_send(send_par);\n");
+            } else {
+              // This should never happen
+              src = mputprintf(src, "TTCN_error(\"Cannot send message correctly %s\");\n", pdef->msg_out.elements[i].targets[j].target_name);
+            }
+            src = mputstr(src, "}\n\n");
             used[n_used] = pdef->msg_out.elements[i].targets[j].target_name;
             n_used++;
           }
@@ -2037,6 +2233,9 @@ void defPortClass(const port_def* pdef, output_struct* output)
       }
     }
     Free(used); // do not delete pointers
+    if (pdef->port_type == USER && !pdef->legacy) {
+      def = mputstr(def, "protected:\n");
+    }
     /* outgoing_call functions */
     for (i = 0; i < pdef->proc_out.nElements; i++) {
       def = mputprintf(def, "virtual void outgoing_call("
@@ -2218,6 +2417,9 @@ void defPortClass(const port_def* pdef, output_struct* output)
   if (pdef->port_type == USER) {
     /* incoming_message() functions for the incoming types of the provider
      * port type */
+    if (!pdef->legacy) {
+      def = mputstr(def, "public:\n");
+    }
     for (i = 0; i < pdef->provider_msg_in.nElements; i++) {
       const port_msg_mapped_type *mapped_type =
         pdef->provider_msg_in.elements + i;
@@ -2274,7 +2476,14 @@ void defPortClass(const port_def* pdef, output_struct* output)
       "}\n", mapped_type->dispname);
       // Print the simple mapping after the not simple mappings
       if (!is_simple || !pdef->legacy) {
+        if (!pdef->legacy) {
+          // If in translation mode then receive according to incoming mappings
+          src = mputstr(src, "if (in_translation_mode()) {\n");
+        }
         src = generate_incoming_mapping(src, pdef, mapped_type, is_simple);
+        if (!pdef->legacy) {
+          src = mputstr(src, "}\n");
+        }
       }
       if (is_simple) {
         src = mputprintf(src,
@@ -2300,6 +2509,9 @@ void defPortClass(const port_def* pdef, output_struct* output)
     }
   } else { /* not user */
     /* incoming_message functions */
+    if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+      def = mputstr(def, "public:\n");
+    }
     for (i = 0; i < pdef->msg_in.nElements; i++) {
       def = mputprintf(def, "void incoming_message(const %s& "
         "incoming_par, component sender_component",
@@ -2317,8 +2529,18 @@ void defPortClass(const port_def* pdef, output_struct* output)
         src = mputprintf(src, ", const %s *sender_address",
           pdef->address_name);
       }
-      src = mputstr(src, ")\n"
-        "{\n"
+      src = mputstr(src, ")\n{\n");
+      if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+        // We forward the incoming_message to the mapped port
+        for (size_t j = 0; j < pdef->n_mapper_name; j++) {
+          src = mputprintf(src,
+            "if (p_%i != NULL) {\n"
+            "p_%i->incoming_message(incoming_par, sender_component);\n"
+            "return;\n}\n",
+            (int)j, (int)j);
+        }
+      }
+      src = mputstr(src,
         "if (!is_started) TTCN_error(\"Port %s is not started but a "
         "message has arrived on it.\", port_name);\n"
         "msg_tail_count++;\n"
@@ -2362,6 +2584,11 @@ void defPortClass(const port_def* pdef, output_struct* output)
         "}\n\n");
     }
   }
+  
+  if ((pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) ||
+      (pdef->port_type == USER && !pdef->legacy)) {
+    def = mputstr(def, "private:\n");
+  }
 
   /* incoming_call functions */
   for (i = 0; i < pdef->proc_in.nElements; i++) {
@@ -2928,54 +3155,18 @@ void generateTestPortSkeleton(const port_def *pdef)
       class_name, base_class_name, class_name,
       pdef->port_type == REGULAR ? " = NULL" : "", class_name);
 
-    // Only print each outgoing_send for each type
-    size_t n_used = 0;
-    const char** used = NULL;
+    if (pdef->port_type == PROVIDER && pdef->n_mapper_name > 0) {
+      fprintf(fp, "public:\n");
+    }
     for (i = 0; i < pdef->msg_out.nElements; i++) {
-      boolean found = FALSE;
-      used = (const char**)Realloc(used, (n_used + pdef->provider_msg_in.nElements + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*));
-      for (size_t k = 0; k < n_used; k++) {
-        if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) {
-          found = TRUE;
-          break;
-        }
-      }
-      if (!found) {
-        fprintf(fp, "\tvoid outgoing_send(const %s& send_par",
-          pdef->msg_out.elements[i].name);
-        if (pdef->testport_type == ADDRESS) {
-          fprintf(fp, ",\n"
-            "\t\tconst %s *destination_address", pdef->address_name);
-        }
-        fputs(");\n", fp);
-        used[n_used] = pdef->msg_out.elements[i].name;
-        n_used++;
-      }
-      if (pdef->port_type == USER && !pdef->legacy) {
-        for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) {
-          found = FALSE;
-          for (size_t k = 0; k < n_used; k++) {
-            if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) {
-              found = TRUE;
-              break;
-            }
-          }
-          if (!found) {
-            fprintf(fp, "\tvoid outgoing_send("
-              "const %s& send_par", pdef->msg_out.elements[i].targets[j].target_name);
-            if (pdef->testport_type == ADDRESS) {
-              fprintf(fp, ",\n"
-                "\t\tconst %s *destination_address", pdef->address_name);
-            }
-            fputs(");\n", fp);
-            
-            used[n_used] = pdef->msg_out.elements[i].targets[j].target_name;
-            n_used++;
-          }
-        }
+      fprintf(fp, "\tvoid outgoing_send(const %s& send_par",
+        pdef->msg_out.elements[i].name);
+      if (pdef->testport_type == ADDRESS) {
+        fprintf(fp, ",\n"
+          "\t\tconst %s *destination_address", pdef->address_name);
       }
+      fputs(");\n", fp);
     }
-    Free(used); // do not delete pointers
     for (i = 0; i < pdef->proc_out.nElements; i++) {
       fprintf(fp, "\tvoid outgoing_call(const %s_call& call_par",
         pdef->proc_out.elements[i].name);
@@ -3124,58 +3315,17 @@ void generateTestPortSkeleton(const port_def *pdef)
       class_name, class_name, class_name, class_name, class_name,
       class_name, class_name, class_name, class_name, class_name,
       class_name);
-    // Only print one outgoing_send for each type
-    // TODO: It is done three times, so maybe we can refactor it in the Ttfcnstuff.cc
-    size_t n_used = 0;
-    const char** used = NULL;
     for (i = 0; i < pdef->msg_out.nElements; i++) {
-      used = (const char**)Realloc(used, (n_used + pdef->msg_out.elements[i].nTargets + 1) * sizeof(const char*));
-      boolean found = FALSE;
-      for (size_t k = 0; k < n_used; k++) {
-        if (strcmp(used[k], pdef->msg_out.elements[i].name) == 0) {
-          found = TRUE;
-          break;
-        }
-      }
-      if (!found) {
-        fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/",
-          class_name, pdef->msg_out.elements[i].name);
-        if (pdef->testport_type == ADDRESS) {
-          fprintf(fp, ",\n"
-            "\tconst %s * /*destination_address*/", pdef->address_name);
-        }
-        fputs(")\n"
-          "{\n\n"
-          "}\n\n", fp);
-        used[n_used] = pdef->msg_out.elements[i].name;
-        n_used++;
-      }
-      if (pdef->port_type == USER && !pdef->legacy) {
-        for (size_t j = 0; j < pdef->msg_out.elements[i].nTargets; j++) {
-          found = FALSE;
-          for (size_t k = 0; k < n_used; k++) {
-            if (strcmp(used[k], pdef->msg_out.elements[i].targets[j].target_name) == 0) {
-              found = TRUE;
-              break;
-            }
-          }
-          if (!found) {
-            fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/",
-            class_name, pdef->msg_out.elements[i].targets[j].target_name);
-            if (pdef->testport_type == ADDRESS) {
-              fprintf(fp, ",\n"
-                "\tconst %s * /*destination_address*/", pdef->address_name);
-            }
-            fputs(")\n"
-              "{\n\n"
-              "}\n\n", fp);
-            used[n_used] = pdef->msg_out.elements[i].targets[j].target_name;
-            n_used++;
-          }
-        }
+      fprintf(fp, "void %s::outgoing_send(const %s& /*send_par*/",
+        class_name, pdef->msg_out.elements[i].name);
+      if (pdef->testport_type == ADDRESS) {
+        fprintf(fp, ",\n"
+          "\tconst %s * /*destination_address*/", pdef->address_name);
       }
+      fputs(")\n"
+        "{\n\n"
+        "}\n\n", fp);
     }
-    Free(used); // do not delete pointers
     for (i = 0; i < pdef->proc_out.nElements; i++) {
       fprintf(fp, "void %s::outgoing_call(const %s_call& /*call_par*/",
         class_name, pdef->proc_out.elements[i].name);
diff --git a/compiler2/ttcn3/port.h b/compiler2/ttcn3/port.h
index c22ba2ff091d00966acad5b23d30cd7fd6044198..930c50b43c332ebee0a05774f8d48ff2d5df19ed 100644
--- a/compiler2/ttcn3/port.h
+++ b/compiler2/ttcn3/port.h
@@ -89,6 +89,17 @@ typedef enum testport_type_t { NORMAL, INTERNAL, ADDRESS } testport_type_t;
 
 typedef enum port_type_t { REGULAR, PROVIDER, USER } port_type_t;
 
+typedef struct port_msg_provider {
+  const char *name; // provider type's name
+  size_t n_out_msg_type_names;
+  const char **out_msg_type_names; // provider's out message list
+} port_msg_prov;
+
+typedef struct port_msg_provider_list {
+  size_t nElements;
+  port_msg_prov *elements;
+} port_msg_prov_list;
+
 typedef struct port_def_tag {
   const char *name;
   const char *dispname;
@@ -102,7 +113,9 @@ typedef struct port_def_tag {
   port_proc_signature_list proc_out; /* from PortTypeBody::out_sigs */
   testport_type_t testport_type;
   port_type_t port_type;
-  const char *provider_name;
+  port_msg_prov_list provider_msg_outlist;
+  const char **mapper_name;
+  size_t n_mapper_name;
   port_msg_mapped_type_list provider_msg_in;
   boolean has_sliding;
   boolean legacy;
diff --git a/core/Port.cc b/core/Port.cc
index 0c025ff01798921e764bb91a8d76b6cad8405a0e..0451572b05ad92e2688ce48daf072d93877dc82b 100644
--- a/core/Port.cc
+++ b/core/Port.cc
@@ -2197,6 +2197,12 @@ void PORT::unmap(const char *system_port)
     Free(unmapped_port);
     throw;
   }
+  
+  // Only valid for provider ports and standard like translation (user) ports.
+  // Currently the requirement is that the port needs to map only when mapped 
+  // to one port. If it would be mapped to more ports then this call would
+  // remove all translation capability.
+  reset_port_variables();
 
   TTCN_Logger::log_port_misc(
     TitanLoggerApi::Port__Misc_reason::port__was__unmapped__from__system,
@@ -2205,6 +2211,10 @@ void PORT::unmap(const char *system_port)
   Free(unmapped_port);
 }
 
+void PORT::reset_port_variables() {
+  
+}
+
 void PORT::process_connect_listen(const char *local_port,
   component remote_component, const char *remote_port,
   transport_type_enum transport_type)
diff --git a/core/Port.hh b/core/Port.hh
index 7e4911297aa177f4b3498859f213ac51d247e72f..4e1c582852744c044eaad086b0222f2bbae45317 100644
--- a/core/Port.hh
+++ b/core/Port.hh
@@ -95,7 +95,7 @@ protected:
   unsigned int msg_head_count, msg_tail_count, proc_head_count,
   proc_tail_count;
   boolean is_active, is_started, is_halted;
-
+  
 private:
   int n_system_mappings;
   char **system_mappings;
@@ -298,7 +298,9 @@ protected:
     Text_Buf& incoming_buf, component sender_component);
   virtual boolean process_exception(const char *signature_name,
     Text_Buf& incoming_buf, component sender_component);
-
+  
+  virtual void reset_port_variables();
+  
 private:
   port_connection *add_connection(component remote_component,
     const char *remote_port, transport_type_enum transport_type);
diff --git a/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn b/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn
index 4767247b8f8b6dea0a44bb5f5775274f136588d2..919feab89e7118f721a9c1ef46423dee83337349 100644
--- a/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn
+++ b/function_test/Semantic_Analyser/port_translation/PortTranslate_SE.ttcn
@@ -13,10 +13,10 @@ module PortTranslate_SE { //^In TTCN-3 module//
 
 	type integer MyInt;
 
-	type port PT1 message map to //In translation capability\:// //^In type definition \`PT1\'\://
+	type port PT1 message map to //In translation capability\:// //^In type definition \`PT1\'\:// //^error\: Duplicate port mappings\, the type \`P1\' appears more than once\.//
 	  P1, //^error\: The referenced port type \`\@PortTranslate_SE\.P1\' must have the \`provider\' attribute//
 	  MyInt, //error\: Type reference \`MyInt\' does not refer to a port type//
-	  P1 { //^error\: The referenced port type \`\@PortTranslate_SE\.P1\' must have the \`provider\' attribute//
+	  P1 {
 		in integer
 	}
 
@@ -96,7 +96,7 @@ module PortTranslate_SE { //^In TTCN-3 module//
 		inout integer
 	}
 
-	type port PT8 message map to P7 { //^In translation capability\:// //^In type definition \`PT8\'\://  //error\: Out message type \`integer\' is not present in the out message list of the port \`P7\'\.//
+	type port PT8 message map to P7 { //^In translation capability\:// //^In type definition \`PT8\'\://  //^error\: Out message type \`integer\'\, or one of the target mappings of out message type \`integer\' is not present in the out or inout message list of the port \`P7\'\.//
 		out integer
 		in charstring
 	}
@@ -177,4 +177,21 @@ module PortTranslate_SE { //^In TTCN-3 module//
 		extension "prototype(fast)"
 	}
 
+
+	type port P9 message {
+		out hexstring
+	} with {
+		extension "provider"
+	}
+
+	type port PT15 message map to P9 { //^In type definition \`PT15\'\:// //^In translation capability\:// //^error\: Out message type \`integer\'\, or one of the target mappings of out message type \`integer\' is not present in the out or inout message list of the port \`P9\'\.//
+		out integer to charstring with int_to_char() : octetstring with int_to_oct()
+	}
+	
+	function int_to_oct(in integer a, out octetstring b) {
+
+	}
+	with {
+		extension "prototype(fast)"
+	}
 }
\ No newline at end of file
diff --git a/regression_test/compileonly/portTranslation/PortTranslate.ttcn b/regression_test/compileonly/portTranslation/PortTranslate.ttcn
index f39f8215169c2e0bf49890297785fb13c021da0f..1d6ef2304e0bcdb0a248ae63a686eba1339bfd53 100644
--- a/regression_test/compileonly/portTranslation/PortTranslate.ttcn
+++ b/regression_test/compileonly/portTranslation/PortTranslate.ttcn
@@ -11,6 +11,7 @@
  ******************************************************************************/
 module PortTranslate {
 
+
 	type port P1 message {
 		in integer
 	} with {
@@ -45,6 +46,29 @@ module PortTranslate {
 		in charstring from octetstring with oct_to_str() : hexstring with hex_to_str() : integer with int_to_str()
 	}
 
+///////////////////////////////////////////////////////////////////////////////
+
+	type component MyComp {
+		port PT1 pt1
+		port PT2 pt2
+		port PT2_ pt2_
+	}
+
+	type component MySystem {
+		port P1 p1
+		port P1_ p1_
+		port P2 p2
+		port P2_ p2_
+	}
+
+	// Check that mapping is possible
+	testcase tc_map() runs on MyComp system MySystem {
+		map(self:pt1, system:p1);
+		map(self:pt2, system:p1);
+		map(self:pt2_, system:p1_);
+		map(self:pt2_, system:p2_);
+	}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 	type port P2 message {
@@ -227,6 +251,48 @@ module PortTranslate {
 	}
 
 
+///////////////////////////////////////////////////////////////////////////////
+
+	type port P19 message {
+		inout integer
+	} with {
+		extension "provider"
+	}
+	
+	type port PT15 message map to P19 {
+		out integer
+		in integer
+	}
+
+///////////////////////////////////////////////////////////////////////////////
+
+	type port P20 message {
+		out charstring
+		out bitstring
+	} with {
+		extension "provider"
+	}
+
+	type port P21 message {
+		out integer
+		out hexstring
+	} with {
+		extension "provider"
+	}
+
+	type port P22 message {
+		out octetstring
+		out hexstring
+	} with {
+		extension "provider"
+	}
+
+	type port PT16 message map to P20, P21, P22 {
+		out integer to charstring with int_to_str() : octetstring with int_to_oct()
+		out bitstring to hexstring with bit_to_hex()
+	}
+
+
 
 
 	/* Conversion functions */
@@ -359,4 +425,5 @@ module PortTranslate {
 		extension "prototype(fast)";
 	}
 
+
 }
\ No newline at end of file
diff --git a/regression_test/portTranslation/Makefile b/regression_test/portTranslation/Makefile
index 91bf361afafbfe1504be5af8a740e81ab312c895..04648ba33a95467adba2179379d8524327a7c6e5 100644
--- a/regression_test/portTranslation/Makefile
+++ b/regression_test/portTranslation/Makefile
@@ -64,7 +64,7 @@ GENERATED_SOURCES += $(GENERATED_SOURCES2)
 endif
 # C/C++ Source & header files of Test Ports, external functions and
 # other modules:
-USER_SOURCES = PT2.cc P1.cc P2.cc
+USER_SOURCES = PT2.cc P1.cc P2.cc P3.cc
 USER_HEADERS = $(USER_SOURCES:.cc=.hh)
 
 # Object files of this project that are needed for the executable test suite:
diff --git a/regression_test/portTranslation/P1.cc b/regression_test/portTranslation/P1.cc
index 65c6611350cb7534e370f23b5fa89831e62cc674..3fb1fd7469c3ce10b493941eda80de093bd4695e 100644
--- a/regression_test/portTranslation/P1.cc
+++ b/regression_test/portTranslation/P1.cc
@@ -72,19 +72,31 @@ void P1_PROVIDER::user_stop()
 
 }
 
-void P1_PROVIDER::outgoing_send(const MyRec& /*send_par*/)
+void P1_PROVIDER::outgoing_send(const MyRec& send_par)
 {
-
+	OCTETSTRING os = send_par.val();
+	incoming_message(os);
 }
 
-void P1_PROVIDER::outgoing_send(const OCTETSTRING& /*send_par*/)
+void P1_PROVIDER::outgoing_send(const OCTETSTRING& send_par)
 {
+	INTEGER integer = send_par.lengthof();
+	incoming_message(integer);
+}
 
+void P1_PROVIDER::outgoing_send(const BITSTRING& send_par)
+{
+	incoming_message(send_par);
 }
 
-void P1_PROVIDER::outgoing_send(const BITSTRING& /*send_par*/)
+void P1_PROVIDER::outgoing_send(const CHARSTRING& send_par)
 {
+	incoming_message(send_par);
+}
 
+void P1_PROVIDER::outgoing_send(const INTEGER& send_par)
+{
+	incoming_message(send_par);
 }
 
 } /* end of namespace */
diff --git a/regression_test/portTranslation/P1.hh b/regression_test/portTranslation/P1.hh
index 48fc4d8bcf259308b9da777732258c12cc3da26b..15dcee8d309609d2e584714cb167e08d1a5d9a44 100644
--- a/regression_test/portTranslation/P1.hh
+++ b/regression_test/portTranslation/P1.hh
@@ -45,11 +45,16 @@ protected:
 	void user_start();
 	void user_stop();
 
+public:
 	void outgoing_send(const MyRec& send_par);
 	void outgoing_send(const OCTETSTRING& send_par);
 	void outgoing_send(const BITSTRING& send_par);
+	void outgoing_send(const CHARSTRING& send_par);
+	void outgoing_send(const INTEGER& send_par);
 	virtual void incoming_message(const INTEGER& incoming_par) = 0;
 	virtual void incoming_message(const BITSTRING& incoming_par) = 0;
+	virtual void incoming_message(const OCTETSTRING& incoming_par) = 0;
+	virtual void incoming_message(const CHARSTRING& incoming_par) = 0;
 };
 
 } /* end of namespace */
diff --git a/regression_test/portTranslation/P2.cc b/regression_test/portTranslation/P2.cc
index f78cd618d50c6ec9d14939c4ee86efe02a14017f..d3e9095b64ee58693150300ba2a53b41df261506 100644
--- a/regression_test/portTranslation/P2.cc
+++ b/regression_test/portTranslation/P2.cc
@@ -72,19 +72,31 @@ void P2_PROVIDER::user_stop()
 
 }
 
-void P2_PROVIDER::outgoing_send(const OCTETSTRING& /*send_par*/)
+void P2_PROVIDER::outgoing_send(const OCTETSTRING& send_par)
 {
-
+	INTEGER integer = send_par.lengthof();
+	incoming_message(integer);
 }
 
-void P2_PROVIDER::outgoing_send(const MyRec& /*send_par*/)
+void P2_PROVIDER::outgoing_send(const MyRec& send_par)
 {
+	OCTETSTRING os = send_par.val();
+	incoming_message(os);
+}
 
+void P2_PROVIDER::outgoing_send(const BITSTRING& send_par)
+{
+	incoming_message(send_par);
 }
 
-void P2_PROVIDER::outgoing_send(const BITSTRING& /*send_par*/)
+void P2_PROVIDER::outgoing_send(const CHARSTRING& send_par)
 {
+	incoming_message(send_par);
+}
 
+void P2_PROVIDER::outgoing_send(const INTEGER& send_par)
+{
+	incoming_message(send_par);
 }
 
 } /* end of namespace */
diff --git a/regression_test/portTranslation/P2.hh b/regression_test/portTranslation/P2.hh
index 1471914fc11af0758f747085e3e0dc771967cdcb..bb66effe97ba7a892ab02a767caf14e323eff2ef 100644
--- a/regression_test/portTranslation/P2.hh
+++ b/regression_test/portTranslation/P2.hh
@@ -45,11 +45,16 @@ protected:
 	void user_start();
 	void user_stop();
 
+public:
 	void outgoing_send(const OCTETSTRING& send_par);
 	void outgoing_send(const MyRec& send_par);
 	void outgoing_send(const BITSTRING& send_par);
+	void outgoing_send(const INTEGER& send_par);
+	void outgoing_send(const CHARSTRING& send_par);
 	virtual void incoming_message(const INTEGER& incoming_par) = 0;
 	virtual void incoming_message(const BITSTRING& incoming_par) = 0;
+	virtual void incoming_message(const OCTETSTRING& incoming_par) = 0;
+	virtual void incoming_message(const CHARSTRING& incoming_par) = 0;
 };
 
 } /* end of namespace */
diff --git a/regression_test/portTranslation/P3.cc b/regression_test/portTranslation/P3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..91d1624a49d66f75ab6694ca8815d28e71416a44
--- /dev/null
+++ b/regression_test/portTranslation/P3.cc
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * 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 "P3.hh"
+
+namespace PortTranslation {
+
+P3::P3(const char *par_port_name)
+	: P3_BASE(par_port_name)
+{
+
+}
+
+P3::~P3()
+{
+
+}
+
+void P3::set_parameter(const char * /*parameter_name*/,
+	const char * /*parameter_value*/)
+{
+
+}
+
+/*void P3::Handle_Fd_Event(int fd, boolean is_readable,
+	boolean is_writable, boolean is_error) {}*/
+
+void P3::Handle_Fd_Event_Error(int /*fd*/)
+{
+
+}
+
+void P3::Handle_Fd_Event_Writable(int /*fd*/)
+{
+
+}
+
+void P3::Handle_Fd_Event_Readable(int /*fd*/)
+{
+
+}
+
+/*void P3::Handle_Timeout(double time_since_last_call) {}*/
+
+void P3::user_map(const char * /*system_port*/)
+{
+
+}
+
+void P3::user_unmap(const char * /*system_port*/)
+{
+
+}
+
+void P3::user_start()
+{
+
+}
+
+void P3::user_stop()
+{
+
+}
+
+void P3::outgoing_send(const MyRec& send_par)
+{
+	OCTETSTRING os = send_par.val();
+	incoming_message(os);
+}
+
+void P3::outgoing_send(const BITSTRING& /*send_par*/)
+{
+
+}
+
+void P3::outgoing_send(const OCTETSTRING& /*send_par*/)
+{
+
+}
+
+} /* end of namespace */
+
diff --git a/regression_test/portTranslation/P3.hh b/regression_test/portTranslation/P3.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ee06a1b105f727bf8b84257ee5d05d8f8d079ab4
--- /dev/null
+++ b/regression_test/portTranslation/P3.hh
@@ -0,0 +1,49 @@
+/******************************************************************************
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef P3_HH
+#define P3_HH
+
+#include "PortTranslation.hh"
+
+namespace PortTranslation {
+
+class P3 : public P3_BASE {
+public:
+	P3(const char *par_port_name = NULL);
+	~P3();
+
+	void set_parameter(const char *parameter_name,
+		const char *parameter_value);
+
+private:
+	/* void Handle_Fd_Event(int fd, boolean is_readable,
+		boolean is_writable, boolean is_error); */
+	void Handle_Fd_Event_Error(int fd);
+	void Handle_Fd_Event_Writable(int fd);
+	void Handle_Fd_Event_Readable(int fd);
+	/* void Handle_Timeout(double time_since_last_call); */
+protected:
+	void user_map(const char *system_port);
+	void user_unmap(const char *system_port);
+
+	void user_start();
+	void user_stop();
+
+	void outgoing_send(const MyRec& send_par);
+	void outgoing_send(const BITSTRING& send_par);
+	void outgoing_send(const OCTETSTRING& send_par);
+};
+
+} /* end of namespace */
+
+#endif
diff --git a/regression_test/portTranslation/PT2.cc b/regression_test/portTranslation/PT2.cc
index bd291d11c6e373240d0c71124d9e37b4271efbf6..096f62da2c8fc37200e3f1dd4e98a06b0aae9817 100644
--- a/regression_test/portTranslation/PT2.cc
+++ b/regression_test/portTranslation/PT2.cc
@@ -74,28 +74,17 @@ void PT2::user_stop()
 void PT2::outgoing_send(const MyRec& send_par)
 {
 	OCTETSTRING os = send_par.val();
-	incoming_message(os);
+	incoming_message(oct2char(os));
 }
 
-void PT2::outgoing_send(const OCTETSTRING& send_par)
+void PT2::outgoing_send(const OCTETSTRING& /*send_par*/)
 {
-	INTEGER integer = send_par.lengthof();
-	incoming_message(integer);
-}
 
-void PT2::outgoing_send(const INTEGER& send_par)
-{
-	incoming_message(send_par);
 }
 
-void PT2::outgoing_send(const CHARSTRING& send_par)
+void PT2::outgoing_send(const BITSTRING& /*send_par*/)
 {
-	incoming_message(send_par);
-}
 
-void PT2::outgoing_send(const BITSTRING& send_par)
-{
-	incoming_message(send_par);
 }
 
 } /* end of namespace */
diff --git a/regression_test/portTranslation/PT2.hh b/regression_test/portTranslation/PT2.hh
index f1857f5fa70cd1aa9c9dd200b4b8ed770e82a162..504c09268f0cc0a2bfb3e192d2632b560a082724 100644
--- a/regression_test/portTranslation/PT2.hh
+++ b/regression_test/portTranslation/PT2.hh
@@ -41,8 +41,6 @@ protected:
 
 	void outgoing_send(const MyRec& send_par);
 	void outgoing_send(const OCTETSTRING& send_par);
-	void outgoing_send(const INTEGER& send_par);
-	void outgoing_send(const CHARSTRING& send_par);
 	void outgoing_send(const BITSTRING& send_par);
 };
 
diff --git a/regression_test/portTranslation/PortTranslation.ttcn b/regression_test/portTranslation/PortTranslation.ttcn
index ffc6010e84301f5813696f1e14f376e5f19fa260..fbf89f62d9b0d0b034990f534cbf6fb77c5be6de 100644
--- a/regression_test/portTranslation/PortTranslation.ttcn
+++ b/regression_test/portTranslation/PortTranslation.ttcn
@@ -64,6 +64,22 @@ module PortTranslation {
 		extension "prototype(fast)";
 	}
 
+	function char_to_char(in charstring i, out charstring j) {
+		if (i == oct2char('010203'O)) {
+			j := "";
+		}
+	} with {
+		extension "prototype(fast)";
+	}
+
+	function MyRec_to_hex(in MyRec i, out hexstring j) {
+		if (i.types == Hex) {
+			j := oct2hex(i.val);
+		}
+	} with {
+		extension "prototype(fast)";
+	}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 	/* Types */
@@ -78,23 +94,30 @@ module PortTranslation {
 	}
 
 	type port P1 message {
-		in integer, bitstring
-		out MyRec, octetstring, bitstring
+		in bitstring, octetstring, charstring
+		out MyRec, octetstring, bitstring, charstring
+		inout integer
 	} with {
 		extension "provider"
 	}
 
 	type port P2 message {
-		in integer, bitstring
-		out octetstring, MyRec, bitstring
+		in integer, bitstring, octetstring, charstring
+		out octetstring, MyRec, bitstring, charstring, integer
 	} with {
 		extension "provider"
 	}
 
+	type port P3 message {
+		out MyRec
+		out bitstring
+		inout octetstring
+	}
+
 	type port PT2 message map to P1, P2 {
-		in charstring
+		in charstring from charstring with char_to_char()
 		in integer, octetstring, hexstring from charstring with char_to_hex() : charstring with char_to_hex2()
-		out MyRec to octetstring with MyRec_to_oct() : integer with MyRec_to_int() : MyRec with MyRec_to_MyRec() : charstring with MyRec_to_char()
+		out MyRec to octetstring with MyRec_to_oct() : integer with MyRec_to_int() : MyRec with MyRec_to_MyRec() : charstring with MyRec_to_char() : hexstring with MyRec_to_hex()
 		out octetstring
 		inout bitstring
 	}
@@ -107,6 +130,8 @@ module PortTranslation {
 	type component System {
 		port P1 p1
 		port P2 p2
+		port P3 p3
+
 	}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -186,6 +211,8 @@ module PortTranslation {
 			[] t.timeout    { setverdict(fail); }
 		}
 		t.stop;
+
+		unmap(self:p, system:p1);
 	}
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -237,10 +264,160 @@ module PortTranslation {
 
 	}
 
+///////////////////////////////////////////////////////////////////////////////
+
+	testcase tc_send2() runs on MyComp system System {
+		map(self:p, system:p2);
+		var MyRec v_rec := { 'ABCDEF'O, Oct };
+
+		// Send octetstring with Oct, so the first mapping function will be successful
+		p.send(v_rec);
+		timer t := 1.0;
+		t.start;
+		alt {
+			[] p.receive(3) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		// Send octetstring with Int so the second mapping function will be successfull
+		v_rec := { '12'O, Int };
+		p.send(v_rec);
+		t.start;
+		alt {
+			[] p.receive(18) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		// Send octetstring with MyRec so the second mapping function will be successfull
+		v_rec := { '123456'O, MyRec };
+		p.send(v_rec);
+		t.start;
+		alt {
+			[] p.receive('123456'O) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		// Send octetstring with None so it will be generate an error because no mapping can handle the message
+		v_rec := { '123456'O, None };
+		@try{
+			p.send(v_rec);
+		} @catch (e) {
+			if (match(e, "Dynamic test case error: Outgoing message of type @PortTranslation.MyRec could not be handled by the type mapping rules on port p.")) {
+				setverdict(pass);
+			} else {
+				setverdict(fail);
+			}
+		}
+
+		// This should be sent too and the implementation of PT2 will send back the length of it.
+		var octetstring os := '12345678'O;
+		p.send(os);
+		t.start;
+		alt {
+			[] p.receive(4) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		var bitstring bs := '010101'B;
+		p.send(bs);
+		t.start;
+		alt {
+			[] p.receive(bs) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		unmap(self:p, system:p2);
+	}
+
+	testcase tc_receive2() runs on MyComp system System {
+		map(self:p, system:p2);
+		var MyRec v_rec := { str2oct("0001"), Char };
+
+		// Send octetstring with Char, so the it will receive the str2hex("0001") hexstring because first it it will be mapped to
+		// charstring with the sending mapping, and it will send back to the port and the charstring will be mapped to hexstring using: char_to_hex
+		p.send(v_rec);
+		timer t := 1.0;
+		t.start;
+		alt {
+			[] p.receive(str2hex("0001")) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		v_rec := { str2oct("0002"), Char };
+
+		// Send octetstring with Char, so the it will receive the str2hex("0002") hexstring because first it it will be mapped to
+		// charstring with the sending mapping, and it will send back to the port and the charstring will be mapped to hexstring using: char_to_hex2
+		p.send(v_rec);
+		t.start;
+		alt {
+			[] p.receive(str2hex("0002")) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+		v_rec := { str2oct("0003"), Char };
+
+		// Send octetstring with Char, so the it will receive the "0003" charstring because first it it will be mapped to
+		// charstring with the sending mapping, and it will send back to the port and the charstring will not be mapped
+		p.send(v_rec);
+		t.start;
+		alt {
+			[] p.receive(charstring:"0003") { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+
+	}
+
+
+	testcase tc_send_and_receive_without_mapping() runs on MyComp system System {
+		map(self:p, system:p3);
+		var MyRec v_rec := { '010203'O, Oct };
+
+		// Send octetstring with Oct, the PT2 port will send it back as charstring without going through char_to_char().
+		p.send(v_rec);
+		timer t := 1.0;
+		t.start;
+		alt {
+			[] p.receive(oct2char('010203'O)) { setverdict(pass); }
+			[] p.receive(integer:?) { setverdict(fail); }
+			[] p.receive(octetstring:?) { setverdict(fail); }
+			[] t.timeout    { setverdict(fail); }
+		}
+		t.stop;
+	}
+
 
 	control {
 		execute(tc_send())
 		execute(tc_receive())
+
+		execute(tc_send2());
+		execute(tc_receive2());
+
+		execute(tc_send_and_receive_without_mapping());
 	}
 
 }
\ No newline at end of file