/*
 * $Id$
 *
 * JSDAI(TM), a way to implement STEP, ISO 10303
 * Copyright (C) 1997-2008, LKSoftWare GmbH, Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation (AGPL v3).
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * JSDAI is a registered trademark of LKSoftWare GmbH, Germany
 * This software is also available under commercial licenses.
 * See also http://www.jsdai.net/
 */

// %modified: 1016210364142 %

/* Generated By:JJTree: Do not edit this line. X_FunctionDecl.java */
package jsdai.expressCompiler;

import jsdai.SExtended_dictionary_schema.*;
import jsdai.lang.*;
import java.util.*;
	

public class X_FunctionDecl extends SimpleNode {
  EFunction_definition fd;
  String name;
  EEntity return_type;
  EParameter return_type_parameter;

  SdaiModel current_model;
  Node local_declarations;

	HashMap hm_labels;
  
  public X_FunctionDecl(int id) {
    super(id);
  }

  public X_FunctionDecl(Compiler2 p, int id) {
    super(p, id);
  }

	EParameter getReturnTypeParameter() {
		return return_type_parameter;
	}

  /** Accept the visitor. **/
  public Object jjtAccept(Compiler2Visitor visitor, Object data)
                   throws SdaiException {
    return visitor.visit(this, data);
  }

	String constructFunctionClassName () throws SdaiException {
	  return constructFunctionProcedureRuleClassName(fd);
	}
	


	String constructFunctionClassName_O () throws SdaiException {
	  String result = "";
		EFunction_definition fd2 = null;
		EFunction_definition fd3 = null;
		String f_name = null;
		
		fd2 = fd;
		
		if (fd == null) {
			result = "_NULL_function_definition_";
			return result;
		}
		
		result = fd2.getName(null);
		result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
		
		for (;;) {
			fd3 = Support.getParentFunctionDefinition(fd2);
			if (fd3 == null) {
				result = "F" + result;
				break;
			} else {
				// still inner function, add names
				f_name = fd3.getName(null);
				result = f_name.substring(0, 1).toUpperCase() + f_name.substring(1).toLowerCase() + "$" + result;
				fd2 = fd3;
			}
		}
	
		return result;	
	
	
	}



/*
	String constructFunctionClassName (EEntity fd4) throws SdaiException {
	  String result = "";
		EAlgorithm_definition fd2 = null;
		EEntity fd3 = null;
		String f_name = null;
		
		if (fd4 instanceof EAlgorithm_definition) {
		} else 
		if (fd4 instanceof EGlobal_rule) {
		} else {
			return "_not_a_proper_parent_of_inner_function_";
		}
		
		fd2 = fd4;
		
		if (fd2 == null) {
			result = "_NULL_function_definition_";
			return result;
		}
		
		result = fd2.getName(null);
		result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
		
		for (;;) {
			fd3 = Support.getParentFunctionProcedureRuleDefinition(fd2);
			if (fd3 == null) {
				result = "F" + result;
				break;
			} else {
				// still inner function, add names
				f_name = fd3.getName(null);
				result = f_name.substring(0, 1).toUpperCase() + f_name.substring(1).toLowerCase() + "$" + result;
				fd2 = fd3;
			}
		}
	
		return result;	
	
	
	}
*/

	String constructFunctionClassName (EFunction_definition fd4) throws SdaiException {
	  String result = "";
		EFunction_definition fd2 = null;
		EFunction_definition fd3 = null;
		String f_name = null;
		
		fd2 = fd4;
		
		if (fd2 == null) {
			result = "_NULL_function_definition_";
			return result;
		}
		
		result = fd2.getName(null);
		result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
		
		for (;;) {
			fd3 = Support.getParentFunctionDefinition(fd2);
			if (fd3 == null) {
				result = "F" + result;
				break;
			} else {
				// still inner function, add names
				f_name = fd3.getName(null);
				result = f_name.substring(0, 1).toUpperCase() + f_name.substring(1).toLowerCase() + "$" + result;
				fd2 = fd3;
			}
		}
	
		return result;	
	
	
	}


	String constructFunctionProcedureRuleClassName (EFunction_definition fd4) throws SdaiException {
	  String result = "";
		EFunction_definition fd2 = null;
		EFunction_definition fd3 = null;
		EEntity fd5 = null;
		EAlgorithm_definition fd6 = null;
		String f_name = null;
		
		fd6 = (EAlgorithm_definition)fd4;
		
		if (fd6 == null) {
			result = "_NULL_function_definition_";
			return result;
		}
		
		result = fd6.getName(null);
		result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
		
		for (;;) {
			// fd3 = Support.getParentFunctionDefinition(fd2);
			if (fd6 != null) {
				fd5 = Support.getParentFunctionProcedureRuleDefinition(fd6);	
			} else {
				fd5 = null;
			}
			if (fd5 == null) {
				result = "F" + result;
				break;
			} else {
				// still inner function, add names
				if (fd5 instanceof EAlgorithm_definition) {
					f_name = ((EAlgorithm_definition)fd5).getName(null);
					fd6 = (EAlgorithm_definition)fd5;
				} else
				if (fd5 instanceof EGlobal_rule) {
					f_name = ((EGlobal_rule)fd5).getName(null);
					fd6 = null;
				}
				result = f_name.substring(0, 1).toUpperCase() + f_name.substring(1).toLowerCase() + "$" + result;
			}
		}
	
		return result;	
	
	
	}


	// useful also for parent which may be also rule
	String constructFunctionProcedureRuleClassName (EEntity fd4) throws SdaiException {
	  String result = "";
		String first_letter = "";
		EFunction_definition fd2 = null;
		EFunction_definition fd3 = null;
		EEntity fd5 = null;
		EAlgorithm_definition fd6 = null;
		String f_name = null;
		
		
		if (fd4 == null) {
			result = "_NULL_function_procedure_rule_definition_";
			return result;
		}
		if (fd4 instanceof EFunction_definition) {
			first_letter = "F";
			result = ((EFunction_definition)fd4).getName(null);
			result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
			fd6 = (EAlgorithm_definition)fd4;
		} else 
		if (fd4 instanceof EProcedure_definition) {
			first_letter = "P";
			result = ((EProcedure_definition)fd4).getName(null);
			result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
			fd6 = (EAlgorithm_definition)fd4;
		} else 
		if (fd4 instanceof EGlobal_rule) {
			first_letter = "R";
			result = ((EGlobal_rule)fd4).getName(null);
			result = result.substring(0, 1).toUpperCase() + result.substring(1).toLowerCase();
			fd6 = null;
			result = first_letter + result;
			return result;
		} else {
			result = "_not_function_procedure_or_rule_";
			return result;
		}
		
		
		
		for (;;) {
			// fd3 = Support.getParentFunctionDefinition(fd2);
			if (fd6 != null) {
				fd5 = Support.getParentFunctionProcedureRuleDefinition(fd6);	
			} else {
				fd5 = null;
			}
			if (fd5 == null) {
				result = first_letter + result;
				break;
			} else {
				// still inner function, add names
				if (fd5 instanceof EAlgorithm_definition) {
					f_name = ((EAlgorithm_definition)fd5).getName(null);
					fd6 = (EAlgorithm_definition)fd5;
				} else
				if (fd5 instanceof EGlobal_rule) {
					f_name = ((EGlobal_rule)fd5).getName(null);
					fd6 = null;
				}
				result = f_name.substring(0, 1).toUpperCase() + f_name.substring(1).toLowerCase() + "$" + result;
			}
		}
	
		return result;	
	
	
	}



  String getType(JavaClass jc) throws SdaiException {
    current_model = jc.model;

    String type = null;
    EEntity rt;
    EParameter pt;
    rt = fd.getReturn_type(null);

    // rt = pt.getParameter_type(null);
    if (rt instanceof EEntity_definition) {
      String base_entity_name = ((EEntity_definition) rt).getName(null);
      String base_name = getEntityPackage((EEntity_definition) rt) + "E" + 
                         base_entity_name.substring(0, 1).toUpperCase() + 
                         base_entity_name.substring(1).toLowerCase();


      // pw.println("\t// attribute:" + attr_name + ", base type: entity " + base_entity_name);
      // pw.println("\tpublic boolean test" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
      // pw.println("\tpublic " + base_name + " get" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
      // pw.println("\tpublic void set" + method_suffix + "(" + entity_name + " type, " + base_name + " value) throws " + "SdaiException;");
      // pw.println("\tpublic void unset" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
      type = base_name;
    } else if (rt instanceof EInteger_type) {
      type = "int";
    } else if (rt instanceof EReal_type) {
      type = "double";
    } else if (rt instanceof ENumber_type) {
      type = "double";
    } else if (rt instanceof EBoolean_type) {
      type = "boolean";
    } else if (rt instanceof EBinary_type) {
      type = "Binary";
    } else if (rt instanceof EData_type) {
      type = "EEntity";
    } else if (rt instanceof EAggregation_type) {
      type = "Aggregate";
    } else if (rt instanceof ELogical_type) {
      type = "int";
    } else if (rt instanceof EString_type) {
      type = "String";
    } else if (rt instanceof EAggregation_type) {
      type = getAggregationTypeBaseTypeString((EAggregation_type) rt);
    } else if (rt instanceof EDefined_type) {
      type = getDefinedTypeUnderlyingTypeString((EDefined_type) rt);
    } else {
      // not supported
      printActive("XP - FunctionDecl: not supported return type, EEntity used: " + rt, jc);
      type = "/* not supported return type */ EEntity";
    }

    return type;
  }

  /*
  For defined types - recursion. If an aggregate inside a defined type - invokes the aggregation method
  For aggregation types - a loop without recursion, handles both nested aggregates and defined types     
      
  Is any special handling of selects necessary? So far this topic postponed.
      
   */
  String getEntityPackage(EEntity_definition eds) throws SdaiException {
    // return an empty string if ed and eds in the same schema, and the package of eds otherwise
    String entity_package = "";
    SdaiModel entity_model = eds.findEntityInstanceSdaiModel();

    //      if (entity_model != current_model) {
    String entity_schema_name = getSchema_definitionFromModel(entity_model).getName(null);

    if (entity_schema_name.equalsIgnoreCase("Sdai_dictionary_schema")) {
      entity_package = "jsdai.dictionary.";
    } else {
      entity_package = "jsdai.S" + entity_schema_name.substring(0, 1).toUpperCase() + 
                       entity_schema_name.substring(1).toLowerCase() + ".";
    }

    //      }
    return entity_package;
  }

  String getAggregationTypeBaseTypeString(EAggregation_type rt1)
                                   throws SdaiException {
    String type = "EEntity /* not supported underlying type of defined type */";
    String comment = "";

    if (rt1 instanceof EArray_type) {
      comment += "ARRAY OF ";
    } else if (rt1 instanceof EBag_type) {
      comment += "BAG OF ";
    } else if (rt1 instanceof ESet_type) {
      comment += "SET OF ";
    } else if (rt1 instanceof EList_type) {
      comment += "LIST OF ";
    }

    EEntity rt = null;
    int aggregate_depth = 1;
    EEntity an_ss = null;
    EEntity ass = rt1;
    String aggr_prefices = "";

    // an_ss = rt1.getElement_type(null);
    boolean element_type_set = rt1.testElement_type(null);

    if (element_type_set) {
      an_ss = rt1.getElement_type(null);
    } else {
      System.out.println("XP: In FunctionDecl, aggregate element type value unset:" + rt1);
    }

    for (;;) {
      boolean done_something = false;

      if (an_ss instanceof EDefined_type) {
        ass = an_ss;

        boolean domain_set = ((EDefined_type) an_ss).testDomain(null);

        if (domain_set) {
          an_ss = ((EDefined_type) an_ss).getDomain(null);
          done_something = true;
        } else {
          System.out.println("XP: In FunctionDecl, in aggregate nested defined type domain unset:" + 
                             an_ss);
        }
      } else if (an_ss instanceof EAggregation_type) {
        aggr_prefices += "a";
        aggregate_depth++;
        ass = an_ss;

        if (ass instanceof EArray_type) {
          comment += "ARRAY OF ";
        } else if (ass instanceof EBag_type) {
          comment += "BAG OF ";
        } else if (ass instanceof ESet_type) {
          comment += "SET OF ";
        } else if (ass instanceof EList_type) {
          comment += "LIST OF ";
        }

        element_type_set = ((EAggregation_type) an_ss).testElement_type(null);

        if (element_type_set) {
          an_ss = ((EAggregation_type) an_ss).getElement_type(null);
          done_something = true;
        } else {
          System.out.println("XP: In FunctionDecl, nested aggregate element type value unset:" + 
                             an_ss);
        }
      }

      if (!done_something) {
        break;
      }
    }

    String aggr_prefix = "A" + aggr_prefices;

    if (rt == null) {
      type = "/* base type of aggregation type is null */ EEntity";
      System.out.println("XP: FunctionDecl: base type of aggregation type is null: " + rt1);
    } else if (rt instanceof EAggregation_type) {
      type = getAggregationTypeBaseTypeString((EAggregation_type) rt);
    } else if (rt instanceof EDefined_type) {
      type = getDefinedTypeUnderlyingTypeString((EDefined_type) rt);
    } else if (rt instanceof ESelect_type) {
      type = getAggregatePackage(aggr_prefix, ass);
    } else if (rt instanceof EEntity_definition) {
      type = getAggregatePackage(aggr_prefix, rt);
    } else if (rt instanceof EInteger_type) {
      type = "" + aggr_prefix + "_integer";
    } else if (rt instanceof EReal_type) {
      type = "" + aggr_prefix + "_double";
    } else if (rt instanceof ENumber_type) {
      type = "" + aggr_prefix + "_double";
    } else if (rt instanceof EBoolean_type) {
      type = "" + aggr_prefix + "_boolean";
    } else if (rt instanceof EData_type) {
      type = "EEntity";
    } else if (rt instanceof EAggregation_type) {
      type = "Aggregate";
    } else if (rt instanceof EBinary_type) {
      type = "" + aggr_prefix + "_binary";
    } else if (rt instanceof EEnumeration_type) {
      type = "" + aggr_prefix + "_enumeration";
    } else if (rt instanceof ELogical_type) {
      type = "" + aggr_prefix + "_enumeration";
    } else if (rt instanceof EString_type) {
      type = "" + aggr_prefix + "_string";
    } else {
      System.out.println("XP: Function Declaration, not yet supported element type in aggregate: " + rt);
      type = "EEntity /* not yet supported element type of aggregate */";
    }

    return type;
  }

  String getAggregatePackage(String aggr_prefix, EEntity ee)
                      throws SdaiException {
    String a_package = "";
    String a_name = "";

    if (ee instanceof ENamed_type) {
      a_name = ((ENamed_type) ee).getName(null);
      a_name = a_name.substring(0, 1).toUpperCase() + a_name.substring(1).toLowerCase();
    }

    SdaiModel a_model = ee.findEntityInstanceSdaiModel();

    if (a_model != current_model) {
      String a_schema_name = getSchema_definitionFromModel(a_model).getName(null);

      if (a_schema_name.equalsIgnoreCase("Sdai_dictionary_schema")) {
        a_package = "jsdai.dictionary.";
      } else {
        a_package = "jsdai.S" + a_schema_name.substring(0, 1).toUpperCase() + 
                    a_schema_name.substring(1).toLowerCase() + ".";
      }
    }

    //      return a_package;
    return a_package + aggr_prefix + a_name;
  }

  ESchema_definition getSchema_definitionFromModel(SdaiModel sm)
                                            throws SdaiException {
    Aggregate ia = sm.getEntityExtentInstances(ESchema_definition.class);
    SdaiIterator iter_inst = ia.createIterator();

    while (iter_inst.next()) {
      ESchema_definition inst = (ESchema_definition) ia.getCurrentMemberObject(iter_inst);

      return inst;
    }

    return null;
  }

  String getDefinedTypeUnderlyingTypeString(EDefined_type rt1)
                                     throws SdaiException {
    String type = "EEntity /* not supported underlying type of defined type */";
    EEntity rt = null;
    boolean domain_set = rt1.testDomain(null);

    if (domain_set) {
      rt = rt1.getDomain(null);
    } else {
      System.out.println("XP: In FunctionDecl, defined type domain unset:" + rt1);
    }

    if (rt == null) {
      type = "/* underlying type of defined type is null */ EEntity";
      System.out.println("XP: FunctionDecl: underlying type of defined type is null: " + rt1);
    } else if (rt instanceof EDefined_type) {
      type = getDefinedTypeUnderlyingTypeString((EDefined_type) rt);
    } else if (rt instanceof EAggregation_type) {
      type = getAggregationTypeBaseTypeString((EAggregation_type) rt);
    } else if (rt instanceof ESelect_type) {
      type = "Object"; // the same as for SELECT attribute, but maybe EEntity is ok? Or branching to specific types.
    } else if (rt instanceof EEnumeration_type) {
      type = "int";
    } else if (rt instanceof EBinary_type) {
      type = "Binary";
    } else if (rt instanceof EInteger_type) {
      type = "int";
    } else if (rt instanceof EReal_type) {
      type = "double";
    } else if (rt instanceof ENumber_type) {
      type = "double";
    } else if (rt instanceof EBoolean_type) {
      type = "boolean";
    } else if (rt instanceof EData_type) {
      type = "EEntity";
    } else if (rt instanceof EAggregation_type) {
      type = "Aggregate";
    } else if (rt instanceof ELogical_type) {
      type = "int";
    } else if (rt instanceof EString_type) {
      type = "String";
    } else {
      type = "EEntity /* not yet supported underlying type of defined type */";
    }

    return type;
  }

  String getParameters() throws SdaiException {
    String parameters = "SdaiContext _context";
    String p_name;
    EEntity pt = null;
    AParameter lp = fd.getParameters(null);
    SdaiIterator ip = lp.createIterator();
    boolean use_value = true;
    boolean first_time = true;

    while (ip.next()) {
      EParameter par = (EParameter) lp.getCurrentMemberObject(ip);
      pt = par.getParameter_type(null);
      p_name = "_e_" + par.getName(null);
      parameters += ", ";

      if (pt instanceof EEntity_definition) {
        String base_entity_name = ((EEntity_definition) pt).getName(null);
        String base_name = getEntityPackage((EEntity_definition) pt) + "E" + 
                           base_entity_name.substring(0, 1).toUpperCase() + 
                           base_entity_name.substring(1).toLowerCase();

        // pw.println("\t// attribute:" + attr_name + ", base type: entity " + base_entity_name);
        // pw.println("\tpublic boolean test" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        // pw.println("\tpublic " + base_name + " get" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        // pw.println("\tpublic void set" + method_suffix + "(" + entity_name + " type, " + base_name + " value) throws " + "SdaiException;");
        // pw.println("\tpublic void unset" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += base_name;
        }
      } else if (pt instanceof EInteger_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "int";
        }
      } else if (pt instanceof EReal_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "double";
        }
      } else if (pt instanceof ENumber_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "double";
        }
      } else if (pt instanceof EBoolean_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "boolean";
        }
      } else if (pt instanceof EBinary_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "Binary";
        }
      } else if (pt instanceof EData_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "EEntity";
        }
      } else if (pt instanceof EAggregation_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "Aggregate";
        }
      } else if (pt instanceof ELogical_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "int";
        }
      } else if (pt instanceof EString_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "String";
        }
      } else if (pt instanceof EAggregation_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += getAggregationTypeBaseTypeString((EAggregation_type) pt);
        }
      } else if (pt instanceof EDefined_type) {
        if (use_value) {
          parameters += "Value";
        } else {
          parameters += getDefinedTypeUnderlyingTypeString((EDefined_type) pt);
        }
      } else {
        // not supported
        System.out.println("XP - FunctionDecl: not supported parameter type, EEntity used: " + pt);

        if (use_value) {
          parameters += "Value";
        } else {
          parameters += "/* not supported parameter type */ EEntity";
        }
      }

      parameters += (" " + p_name);
    }

    return parameters;
  }

  String getParameters_previous() throws SdaiException {
    String parameters = "";
    String p_name;
    EEntity pt = null;
    AParameter lp = fd.getParameters(null);
    SdaiIterator ip = lp.createIterator();
    boolean first_time = true;

    while (ip.next()) {
      EParameter par = (EParameter) lp.getCurrentMemberObject(ip);
      pt = par.getParameter_type(null);
      p_name = par.getName(null);

      if (first_time) {
        first_time = false;
      } else {
        parameters += ", ";
      }

      if (pt instanceof EEntity_definition) {
        String base_entity_name = ((EEntity_definition) pt).getName(null);
        String base_name = getEntityPackage((EEntity_definition) pt) + "E" + 
                           base_entity_name.substring(0, 1).toUpperCase() + 
                           base_entity_name.substring(1).toLowerCase();


        // pw.println("\t// attribute:" + attr_name + ", base type: entity " + base_entity_name);
        // pw.println("\tpublic boolean test" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        // pw.println("\tpublic " + base_name + " get" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        // pw.println("\tpublic void set" + method_suffix + "(" + entity_name + " type, " + base_name + " value) throws " + "SdaiException;");
        // pw.println("\tpublic void unset" + method_suffix + "(" + entity_name + " type) throws " + "SdaiException;");
        parameters += base_name;
      } else if (pt instanceof EInteger_type) {
        parameters += "int";
      } else if (pt instanceof EReal_type) {
        parameters += "double";
      } else if (pt instanceof ENumber_type) {
        parameters += "double";
      } else if (pt instanceof EBoolean_type) {
        parameters += "boolean";
      } else if (pt instanceof EBinary_type) {
        parameters += "Binary";
      } else if (pt instanceof EData_type) {
        parameters += "EEntity";
      } else if (pt instanceof EAggregation_type) {
        parameters += "Aggregate";
      } else if (pt instanceof ELogical_type) {
        parameters += "int";
      } else if (pt instanceof EString_type) {
        parameters += "String";
      } else if (pt instanceof EAggregation_type) {
        parameters += getAggregationTypeBaseTypeString((EAggregation_type) pt);
      } else if (pt instanceof EDefined_type) {
        parameters += getDefinedTypeUnderlyingTypeString((EDefined_type) pt);
      } else {
        // not supported
        System.out.println("XP - FunctionDecl: not supported parameter type, EEntity used: " + pt);
        parameters += "/* not supported parameter type */ EEntity";
      }

      parameters += p_name;
    }

    return parameters;
  }

  String getParameters_old() throws SdaiException {
    String parameters = "";
    String p_name;
    EEntity pt = null;
    AParameter lp = fd.getParameters(null);
    SdaiIterator ip = lp.createIterator();
    boolean first_time = true;

    while (ip.next()) {
      EParameter par = (EParameter) lp.getCurrentMemberObject(ip);
      pt = par.getParameter_type(null);
      p_name = par.getName(null);

      if (first_time) {
        first_time = false;
      } else {
        parameters += ", ";
      }

      if (pt instanceof EInteger_type) {
        parameters += "int ";
      } else if (pt instanceof ELogical_type) {
        parameters += "int ";
      } else if (pt instanceof EBoolean_type) {
        parameters += "boolean ";
      } else if (pt instanceof ENumber_type) {
        parameters += "double ";
      } else if (pt instanceof EReal_type) {
        parameters += "double ";
      } else if (pt instanceof EString_type) {
        parameters += "String ";
      } else if (pt instanceof EData_type) {
        parameters += "EEntity ";
      } else if (pt instanceof ESet_type) {
        EEntity element;

        if (((ESet_type) pt).testElement_type(null)) {
          element = ((ESet_type) pt).getElement_type(null);
        } else {
          element = null;
          System.out.println("## In FunctionDecl - getParameters - element_type is NULL: " + 
                             fd.getName(null));
        }

        if (element == null) {
          parameters += "/* element of SET type is NULL */ AEntity ";
        } else if (element instanceof ESimple_type) {
          if (element instanceof EString_type) {
            parameters += "A_string ";
          } else if (element instanceof EInteger_type) {
            parameters += "A_integer ";
          } else if (element instanceof ELogical_type) {
            parameters += "A_integer ";
          } else if (element instanceof ENumber_type) {
            parameters += "A_double ";
          } else if (element instanceof EReal_type) {
            parameters += "A_double ";
          } else if (element instanceof EBoolean_type) {
            parameters += "A_boolean ";
          } else {
            parameters += "/* Set of simple type */ AEntity ";
          }
        } else if (element instanceof EAggregation_type) {
          parameters += "/* SET of aggregate */ AEntity ";
        } // may go deeper later on
        else if (element instanceof EEntity_definition) {
          parameters += "/* SET OF some entity */ AEntity ";
        } // may add specific entity - may need short form support
        else {
          parameters += "/* SET of other type */ AEntity ";
        }
      } else if (pt instanceof EList_type) {
        EEntity element;

        if (((EList_type) pt).testElement_type(null)) {
          element = ((EList_type) pt).getElement_type(null);
        } else {
          element = null;
          System.out.println("## In FunctionDecl - getParameters - element_type is NULL: " + 
                             fd.getName(null));
        }

        if (element == null) {
          parameters += "/* element of LIST type is NULL */ AEntity ";
        } else if (element instanceof ESimple_type) {
          if (element instanceof EString_type) {
            parameters += "A_string ";
          } else if (element instanceof EInteger_type) {
            parameters += "A_integer ";
          } else if (element instanceof ELogical_type) {
            parameters += "A_integer ";
          } else if (element instanceof ENumber_type) {
            parameters += "A_double ";
          } else if (element instanceof EReal_type) {
            parameters += "A_double ";
          } else if (element instanceof EBoolean_type) {
            parameters += "A_boolean ";
          } else {
            parameters += "/* List of simple type */ AEntity ";
          }
        } else if (element instanceof EAggregation_type) {
          parameters += "/* List of aggregate */ AEntity ";
        } // may go deeper later on
        else if (element instanceof EEntity_definition) {
          parameters += "/* List OF some entity */ AEntity ";
        } // may add specific entity - may need short form support
        else {
          parameters += "/* List of other type */ AEntity ";
        }
      } else if (pt instanceof EArray_type) {
        EEntity element;

        if (((EArray_type) pt).testElement_type(null)) {
          element = ((EArray_type) pt).getElement_type(null);
        } else {
          element = null;
          System.out.println("## In FunctionDecl - getParameters - element_type is NULL: " + 
                             fd.getName(null));
        }

        if (element == null) {
          parameters += "/* element of Array type is NULL */ AEntity ";
        } else if (element instanceof ESimple_type) {
          if (element instanceof EString_type) {
            parameters += "A_string ";
          } else if (element instanceof EInteger_type) {
            parameters += "A_integer ";
          } else if (element instanceof ELogical_type) {
            parameters += "A_integer ";
          } else if (element instanceof ENumber_type) {
            parameters += "A_double ";
          } else if (element instanceof EReal_type) {
            parameters += "A_double ";
          } else if (element instanceof EBoolean_type) {
            parameters += "A_boolean ";
          } else {
            parameters += "/* Array of simple type */ AEntity ";
          }
        } else if (element instanceof EAggregation_type) {
          parameters += "/* Array of aggregate */ AEntity ";
        } // may go deeper later on
        else if (element instanceof EEntity_definition) {
          parameters += "/* Array OF some entity */ AEntity ";
        } // may add specific entity - may need short form support
        else {
          parameters += "/* Array of other type */ AEntity ";
        }
      } else if (pt instanceof EBag_type) {
        EEntity element;

        if (((EBag_type) pt).testElement_type(null)) {
          element = ((EBag_type) pt).getElement_type(null);
        } else {
          element = null;
          System.out.println("## In FunctionDecl - getParameters - element_type is NULL: " + 
                             fd.getName(null));
        }

        if (element == null) {
          parameters += "/* element of BAG type is NULL */ AEntity ";
        } else if (element instanceof ESimple_type) {
          if (element instanceof EString_type) {
            parameters += "A_string ";
          } else if (element instanceof EInteger_type) {
            parameters += "A_integer ";
          } else if (element instanceof ELogical_type) {
            parameters += "A_integer ";
          } else if (element instanceof ENumber_type) {
            parameters += "A_double ";
          } else if (element instanceof EReal_type) {
            parameters += "A_double ";
          } else if (element instanceof EBoolean_type) {
            parameters += "A_boolean ";
          } else {
            parameters += "/* Bag of simple type */ AEntity ";
          }
        } else if (element instanceof EAggregation_type) {
          parameters += "/* Bag of aggregate */ AEntity ";
        } // may go deeper later on
        else if (element instanceof EEntity_definition) {
          parameters += "/* Bag OF some entity */ AEntity ";
        } // may add specific entity - may need short form support
        else {
          parameters += "/* Bag of other type */ AEntity ";
        }
      } else if (pt instanceof EEntity_definition) {
        String specific_entity_type_name = ((EEntity_definition) pt).getName(null);
        String entity_type_name = "E" + specific_entity_type_name.substring(0, 1).toUpperCase() + 
                                  specific_entity_type_name.substring(1).toLowerCase();

        // String schema_package = "jsdai" + File.separator + "S" + schema_name.substring(0,1).toUpperCase() + schema_name.substring(1).toLowerCase();
        String entity_schema_name = "";
        String complete_entity_type_name = entity_schema_name + entity_type_name + " ";
        parameters += complete_entity_type_name;
      } else {
        System.out.println("XP - FunctionRef: not yet supported parameter type: " + pt);
        parameters += " /* not (yet) supported parameter type */ EEntity ";
      }

      parameters += p_name;
    }

    return parameters;
  }

  void restoreNonVar(JavaClass jc) throws SdaiException {
    // makes variables with required parameter types,
    // creates Value instances with declared types,
    // and sets arguments as values,
    // that ensures type checking. Also in parameter nodes, the name field is changed to this new variable name.
    // that ensures non-VAR behaviour of parameters, all the references to parameters
    // now will be changed to references to these new variables
    String p_name;
    String new_name;
    String name_prefix = "_nonvar_";
    String variable_string;
    String static_type_string;
    EEntity pt = null;
    AParameter lp = fd.getParameters(null);
    SdaiIterator ip = lp.createIterator();
    boolean use_value = true;

    while (ip.next()) {
      EParameter par = (EParameter) lp.getCurrentMemberObject(ip);
      pt = par.getParameter_type(null);
      p_name = "_e_" + par.getName(null);
      new_name = name_prefix + p_name;
//      new_name = name_prefix + par.getName(null);


      //      static_type_string = getStaticTypeString(pt, jc);
//      variable_string = "\t\t" + p_name + ".set(_context, " + new_name + ");";
      variable_string = "\t\t" + p_name + ".set(" + new_name + ");";
      jc.pw.println(variable_string);
    }
  }

  void makeNonVar(JavaClass jc) throws SdaiException {
    // makes variables with required parameter types,
    // creates Value instances with declared types,
    // and sets arguments as values,
    // that ensures type checking. Also in parameter nodes, the name field is changed to this new variable name.
    // that ensures non-VAR behaviour of parameters, all the references to parameters
    // now will be changed to references to these new variables

    String p_name;
    String new_name;
    String name_prefix = "_nonvar_";
    String variable_string;
    String static_type_string = null;
    EEntity pt = null;
    AParameter lp = fd.getParameters(null);
    SdaiIterator ip = lp.createIterator();
    boolean use_value = true;
		hm_labels = new HashMap();

  	jc.parameter_declarations_str += "\t// declaration of non-VAR parameters\n";
  	jc.parameter_initializations_str += "\n\t\t// initialization of non-VAR parameters\n";
    while (ip.next()) {
      EParameter par = (EParameter) lp.getCurrentMemberObject(ip);
      pt = par.getParameter_type(null);
      p_name = "_e_" + par.getName(null);
      new_name = name_prefix + p_name;
//      new_name = name_prefix + par.getName(null);
			A_string labels = null;
			String label = null;
			if (par.testType_labels(null)) {
				labels = par.getType_labels(null);
				if (labels.getMemberCount() > 0) {
					// ignore nested labels, at least for now
					label = labels.getByIndex(1);
				}
			}
			if (label != null) {
				// see if we already have this label
				if (!(hm_labels.containsKey(label))) {
					hm_labels.put(label, p_name);
				}
			}

      static_type_string = getStaticTypeString(par, jc);


      //	  jc.pw.println("TYPE_NAME AFTER CRAP:" +static_type_string);	
//      variable_string = "\t\tValue " + new_name + " = Value.alloc(" + static_type_string + ").set(_context, " + p_name + ");";

//      variable_string = "\t\tValue " + new_name + " = Value.alloc(" + static_type_string + ").set(" + p_name + ");";
      jc.parameter_declarations_str  += "\tValue " + new_name + ";\n";
      jc.parameter_initializations_str += "\t\t" + new_name + " = Value.alloc(" + static_type_string + ").set(" + p_name + ");\n";
//      jc.pw.println(variable_string);
    }
  	jc.parameter_declarations_str += "\t// end of declaration of non-VAR parameters\n";
  	jc.parameter_initializations_str += "\t\t// end of initialization of non-VAR parameters\n";
  }

  String getStaticTypeString(EParameter par0, JavaClass jc)
                      throws SdaiException {
    current_model = jc.model;

		return_type_parameter = ((X_FunctionHead)children[0]).return_type_parameter;

    String type_name = "";
    EEntity rt = par0.getParameter_type(null);
    String p_name = "_e_" + par0.getName(null);
		A_string labels = null;
		String label = null;

		if (par0.testType_labels(null)) {
			labels = par0.getType_labels(null);
			if (labels.getMemberCount() > 0) {
				// ignore nested labels, at least for now
				label = labels.getByIndex(1);
			}
		}
		if (label != null) {
			// see if we already have this label
			if (hm_labels.containsKey(label)) {
				String first_name = (String)hm_labels.get(label);
				if (!(first_name.equals(p_name))) {
					type_name = first_name + ".getActualType()";
					return type_name;
				}
			}
				}
    

    // EEntity rt;
    EParameter pt;

    // rt = parameter_type.getParameter_type(null);
    // here we need the string for every type possible: entity, defined_type or no-name type
    if (rt instanceof EEntity_definition) {
      String base_entity_name = ((EEntity_definition) rt).getName(null);
      String base_name = getEntityPackage((EEntity_definition) rt) + "C" + 
                         base_entity_name.substring(0, 1).toUpperCase() + 
                         base_entity_name.substring(1).toLowerCase();
      type_name = base_name + ".definition";

      return type_name;
    } else if (rt instanceof EDefined_type) {
      String base_entity_name = ((EDefined_type) rt).getName(null);
      String base_name = constructTypeAndFromReferencedSchemaClass((EDefined_type) rt);
      type_name = base_name + "_st_" + ((EDefined_type) rt).getName(null);

      return type_name;

      //      type_name = "_st_" + (( jsdai.SExtended_dictionary_schema.EDefined_type )rt).getName(null);
    } else if (rt instanceof ESimple_type) {
      // check the types that may have WIDTH FIXED PRECISSION - string binary real
      if (rt instanceof EString_type) {
        if (!((EString_type) rt).testWidth(null)) {
          type_name = "ExpressTypes.STRING_TYPE";
        } else {
          type_name = "_ST_STRING";

          EBound s_width = ((EString_type) rt).getWidth(null);

          if (s_width instanceof EInteger_bound) {
            EInteger_bound i_width = (EInteger_bound) s_width;
            boolean integer_bound_set = i_width.testBound_value(null);

            if (integer_bound_set) {
              int width_value = i_width.getBound_value(null);
              type_name += ("_" + width_value);
            }
          }

          boolean fixed_present = ((EString_type) rt).testFixed_width(null);

          if (fixed_present) {
            boolean fixed_value = ((EString_type) rt).getFixed_width(null);

            if (fixed_value) {
              type_name += "_FIXED";
            }
          }
        }
      } else if (rt instanceof EBinary_type) {
        if (!((EBinary_type) rt).testWidth(null)) {
          type_name = "ExpressTypes.BINARY_TYPE";
        } else {
          type_name = "_ST_BINARY";

          EBound b_width = ((EBinary_type) rt).getWidth(null);

          if (b_width instanceof EInteger_bound) {
            EInteger_bound i_width = (EInteger_bound) b_width;
            boolean integer_bound_set = i_width.testBound_value(null);

            if (integer_bound_set) {
              int width_value = i_width.getBound_value(null);
              type_name += ("_" + width_value);
            }
          }

          boolean fixed_present = ((EBinary_type) rt).testFixed_width(null);

          if (fixed_present) {
            boolean fixed_value = ((EBinary_type) rt).getFixed_width(null);

            if (fixed_value) {
              type_name += "_FIXED";
            }
          }
        }
      } else if (rt instanceof EReal_type) {
        if (!((EReal_type) rt).testPrecision(null)) {
          type_name = "ExpressTypes.REAL_TYPE";
        } else {
          type_name = "_ST_REAL";

          EBound r_precision = ((EReal_type) rt).getPrecision(null);

          if (r_precision instanceof EInteger_bound) {
            EInteger_bound i_precision = (EInteger_bound) r_precision;

            if (i_precision.testBound_value(null)) {
              int precision_value = i_precision.getBound_value(null);
              type_name += ("_" + precision_value);
            }
          }
        }
      } else if (rt instanceof EInteger_type) {
        type_name = "ExpressTypes.INTEGER_TYPE";
      } else if (rt instanceof ENumber_type) {
        type_name = "ExpressTypes.NUMBER_TYPE";
      } else if (rt instanceof ELogical_type) {
        type_name = "ExpressTypes.LOGICAL_TYPE";
      } else if (rt instanceof EBoolean_type) {
        type_name = "ExpressTypes.BOOLEAN_TYPE";
      }
    } else if (rt instanceof EAggregation_type) {
      type_name = "_st" + 
                  constructAggregationTypeBaseTypeNameString((EAggregation_type) rt, current_model)
                    .toLowerCase();
    } else if (rt instanceof EData_type) {
      String data_name = null;

      if (((EData_type) rt).testName(null)) {
        data_name = ((EData_type) rt).getName(null);

        if (data_name.equals("_GENERIC")) {
          type_name = "ExpressTypes.GENERIC_TYPE";
        } else 
        if (data_name.equals("_ENTITY")) {
          type_name = "ExpressTypes.GENERIC_ENTITY_TYPE";
				}
      }
    } else {
      // error?
    }

    // standard express types
    if (type_name.equals("_st_generallist_0_generic")) {
      return "ExpressTypes.LIST_GENERIC_TYPE";
    }

    if (type_name.equals("_st_generalset_0_generic")) {
      return "ExpressTypes.SET_GENERIC_TYPE";
    }

    if (type_name.equals("_st_generalbag_0_generic")) {
      return "ExpressTypes.BAG_GENERIC_TYPE";
    }

    if (type_name.equals("_st_generalset_0_string")) {
      return "ExpressTypes.SET_STRING_TYPE";
    }

    // do we need separate types in dictionary for set of string and generalset of string?
    // if (type_name.equals("_st_set_0_string")) {
    // return "ExpressTypes.SET_STRING_TYPE";
    // }
    if (type_name.equals("_st_aggregate_generic")) {
      return "ExpressTypes.AGGREGATE_GENERIC_TYPE";
    }

    //	System.out.println("L:" +type_name);	
    if (type_name.length() > "ExpressTypes".length()) {
      if (type_name.substring(0, "ExpressTypes".length()).equals("ExpressTypes")) {
        return type_name;
      }
    }

    if (rt instanceof EEntity_definition) {
      //				type_name = constructTypeSchemaClass(jc) + type_name;
    } else {
      type_name = type_name.toLowerCase();
      type_name = constructTypeSchemaClass(jc, rt) + type_name;
    }

    if (rt instanceof EDefined_type) {
      type_name = "(jsdai.dictionary.EData_type)" + type_name;
    }

    return type_name;
  }

  String constructTypeSchemaClass(JavaClass jc, EEntity rt) throws SdaiException {
    current_model = jc.model;

    String model_name = current_model.getName();
    String schema_name;
    if (rt instanceof EAggregation_type) {
    	// at least for this case we need not the current model, but the model where the aggregation type is defined,
    	// it may be the current model or a different model, the model of an interfaced schema
    	// the static variable for the aggregate is defined in the S... class of the package of that schema
    	// The same approach may be needed also for non-aggregates, so far everyhing seems to be ok, 
    	// so not changing for other cases so far, for non-aggregates non-java inheritance duplicates a number of things,
    	// so that the current model may be needed instead
    	// even for aggregates there may be unexpected issues, so thorough testing will be needed
// System.out.println("<> rt model: " + rt.findEntityInstanceSdaiModel());    	
    	model_name = rt.findEntityInstanceSdaiModel().getName();
    }


    if (model_name.length() > 16) {
      String part_model_name = model_name.substring(model_name.length() - 16);

      if (part_model_name.equalsIgnoreCase("_DICTIONARY_DATA")) {
        schema_name = model_name.substring(0, model_name.length() - 16);
      } else {
        schema_name = model_name;
      }
    } else {
      schema_name = model_name;
    }

    //     String type_schema_class = "jsdai.S" + schema_name.substring(0,1).toUpperCase() + schema_name.substring(1).toLowerCase() + ".class";
    String type_schema_class = "jsdai.S" + schema_name.substring(0, 1).toUpperCase() + 
                               schema_name.substring(1).toLowerCase() + ".S" + 
                               schema_name.substring(0, 1).toUpperCase() + 
                               schema_name.substring(1).toLowerCase() + ".";

    return type_schema_class;
  }

  String constructTypeAndFromReferencedSchemaClass(EDefined_type ed)
                                            throws SdaiException {
    String type_schema_class = "";
    SdaiModel entity_model = ed.findEntityInstanceSdaiModel();

    //    if (entity_model != current_model) {
    String schema_name = getSchema_definitionFromModel(entity_model).getName(null);
    type_schema_class = "jsdai.S" + schema_name.substring(0, 1).toUpperCase() + 
                        schema_name.substring(1).toLowerCase() + ".S" + 
                        schema_name.substring(0, 1).toUpperCase() + 
                        schema_name.substring(1).toLowerCase() + ".";

    //    }
    return type_schema_class;
  }

  String constructAggregationTypeBaseTypeNameString(EAggregation_type rt1, SdaiModel current_model)
                                             throws SdaiException {
    String type_name = "";

    if (rt1 instanceof EArray_type) {
      type_name += "_GENERALARRAY";
      type_name += constructArrayBoundNames((EArray_type) rt1);

      // additionally - OPTIONAL and UNIQUE.
      if (((EArray_type) rt1).testOptional_flag(null)) {
        if (((EArray_type) rt1).getOptional_flag(null)) {
          type_name += "_OPTIONAL";
        }
      }

      if (((EArray_type) rt1).testUnique_flag(null)) {
        if (((EArray_type) rt1).getUnique_flag(null)) {
          type_name += "_UNIQUE";
        }
      }
    } else if (rt1 instanceof EBag_type) {
      type_name += "_GENERALBAG";
      type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) rt1);
    } else if (rt1 instanceof ESet_type) {
      type_name += "_GENERALSET";
      type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) rt1);
    } else if (rt1 instanceof EList_type) {
      type_name += "_GENERALLIST";
      type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) rt1);

      // UNIQUE
      if (((EList_type) rt1).testUnique_flag(null)) {
        if (((EList_type) rt1).getUnique_flag(null)) {
          type_name += "_UNIQUE";
        }
      }
    } else {
      // maybe AGGREGATE
      String aggr_name;

      if (rt1.testName(null)) {
        aggr_name = rt1.getName(null);

        if (aggr_name.substring(0, "_AGGREGATE".length()).equals("_AGGREGATE")) {
          type_name = "_AGGREGATE"; //aggr_name;
        } else {
          type_name += "_UNKNOWNAGGREGATE";
        }
      } else {
        type_name += "_NONAMEAGGREGATE";
      }
    }

    EEntity rt = null;
    int aggregate_depth = 1;
    EEntity an_ss = null;
    EEntity ass = rt1;
    String aggr_prefices = "";

    // an_ss = rt1.getElement_type(null);
    boolean element_type_set = rt1.testElement_type(null);

    if (element_type_set) {
      an_ss = rt1.getElement_type(null);
      rt = an_ss;
    } else {
      System.out.println("XP: In LocalVariable, aggregate element type value unset:" + rt1);
    }

    for (;;) {
      boolean done_something = false;

      if (an_ss instanceof EDefined_type) {
        //            ass = an_ss;
        //            boolean domain_set = ((EDefined_type)an_ss).testDomain(null);
        //            if (domain_set) {
        //               an_ss = ((EDefined_type)an_ss).getDomain(null);
        //               done_something = true;
        //            } else {
        //               System.out.println("XP: constructing type name, in aggregate nested defined type domain unset:" + an_ss);
        //            }
      } else if (an_ss instanceof EAggregation_type) {
        aggr_prefices += "a";
        aggregate_depth++;
        ass = an_ss;

        if (ass instanceof EArray_type) {
          type_name += "_GENERALARRAY";
          type_name += constructArrayBoundNames((EArray_type) ass);

          if (((EArray_type) ass).testOptional_flag(null)) {
            if (((EArray_type) ass).getOptional_flag(null)) {
              type_name += "_OPTIONAL";
            }
          }

          if (((EArray_type) ass).testUnique_flag(null)) {
            if (((EArray_type) ass).getUnique_flag(null)) {
              type_name += "_UNIQUE";
            }
          }
        } else if (ass instanceof EBag_type) {
          type_name += "_GENERALBAG";
          type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) ass);
        } else if (ass instanceof ESet_type) {
          type_name += "_GENERALSET";
          type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) ass);
        } else if (ass instanceof EList_type) {
          type_name += "_GENERALLIST";
          type_name += constructBagListSetBoundNames((EVariable_size_aggregation_type) ass);

          if (((EList_type) ass).testUnique_flag(null)) {
            if (((EList_type) ass).getUnique_flag(null)) {
              type_name += "_UNIQUE";
            }
          }
        } else if (ass instanceof EAggregation_type) {
          // maybe AGGREGATE
          String aggr_name;

          if (((EAggregation_type) ass).testName(null)) {
            aggr_name = ((EAggregation_type) ass).getName(null);

            if (aggr_name.substring(0, "_AGGREGATE".length()).equals("_AGGREGATE")) {
              type_name = "_AGGREGATE"; //aggr_name;
            } else {
              type_name += "_UNKNOWNAGGREGATE";
            }
          } else {
            type_name += "_NONAMEAGGREGATE";
          }
        } else {
          type_name += "_NOTAGGREGATE";
        }

        element_type_set = ((EAggregation_type) an_ss).testElement_type(null);

        if (element_type_set) {
          an_ss = ((EAggregation_type) an_ss).getElement_type(null);
          done_something = true;
        } else {
          System.out.println(
                "XP: constructing type names, nested aggregate element type value unset:" + 
                an_ss);
        }
      }

      if (!done_something) {
        break;
      }
    }

    String aggr_prefix = "A" + aggr_prefices;
    rt = an_ss;

    if (rt == null) {
      type_name += "_NULL";
      System.out.println("XP: constructing type names: base type of aggregation type is null: " + 
                         rt1);
    } else if (rt instanceof EAggregation_type) {
      type_name += constructAggregationTypeBaseTypeNameString((EAggregation_type) rt, current_model);
    } else
    //      if (rt instanceof EAggregation_type) {
    //         type_name += "_AGGREGATE";
    //    } else
    if (rt instanceof EDefined_type) {
      type_name += constructDefinedTypeUnderlyingTypeNameString((EDefined_type) rt);
    } else if (rt instanceof ESelect_type) {
      // will not reach this case
      type_name += constructNameWithAggregatePackage(aggr_prefix, ass, current_model);
    } else if (rt instanceof EEntity_definition) {
      type_name += constructNameWithAggregatePackage(aggr_prefix, rt, current_model);
    } else if (rt instanceof EInteger_type) {
      type_name += "_INTEGER";
    } else if (rt instanceof EReal_type) {
      type_name += "_REAL";

      EReal_type real_type = (EReal_type) rt;
      boolean precision_present = real_type.testPrecision(null);

      if (precision_present) {
        EBound b_precision = real_type.getPrecision(null);

        if (b_precision instanceof EInteger_bound) {
          EInteger_bound i_precision = (EInteger_bound) b_precision;
          boolean integer_bound_set = i_precision.testBound_value(null);

          if (integer_bound_set) {
            int precision_value = i_precision.getBound_value(null);
            type_name += ("_" + precision_value);
          }
        }
      }
    } else if (rt instanceof ENumber_type) {
      type_name += "_NUMBER";
    } else if (rt instanceof EBoolean_type) {
      type_name += "_BOOLEAN";
    } else if (rt instanceof EBinary_type) {
      type_name += "_BINARY";

      EBinary_type binary_type = (EBinary_type) rt;
      boolean width_present = binary_type.testWidth(null);

      if (width_present) {
        EBound b_width = binary_type.getWidth(null);

        if (b_width instanceof EInteger_bound) {
          EInteger_bound i_width = (EInteger_bound) b_width;
          boolean integer_bound_set = i_width.testBound_value(null);

          if (integer_bound_set) {
            int width_value = i_width.getBound_value(null);
            type_name += ("_" + width_value);
          }
        }

        boolean fixed_present = binary_type.testFixed_width(null);

        if (fixed_present) {
          boolean fixed_value = binary_type.getFixed_width(null);

          if (fixed_value) {
            type_name += "_FIXED";
          }
        }
      }
    } else if (rt instanceof EEnumeration_type) {
      // will not reach
      type_name += "_ENUMERATION";
    } else if (rt instanceof ELogical_type) {
      type_name += "_LOGICAL";
    } else if (rt instanceof EString_type) {
      type_name += "_STRING";

      EString_type string_type = (EString_type) rt;
      boolean width_present = string_type.testWidth(null);

      if (width_present) {
        EBound b_width = string_type.getWidth(null);

        if (b_width instanceof EInteger_bound) {
          EInteger_bound i_width = (EInteger_bound) b_width;
          boolean integer_bound_set = i_width.testBound_value(null);

          if (integer_bound_set) {
            int width_value = i_width.getBound_value(null);
            type_name += ("_" + width_value);
          }
        }

        boolean fixed_present = string_type.testFixed_width(null);

        if (fixed_present) {
          boolean fixed_value = string_type.getFixed_width(null);

          if (fixed_value) {
            type_name += "_FIXED";
          }
        }
      }
    } else if (rt instanceof EData_type) {
       String data_name = null;

      if (((EData_type) rt).testName(null)) {
        data_name = ((EData_type) rt).getName(null);

        if (data_name.equals("_GENERIC")) {
		      type_name += "_GENERIC";
    //      type_name = "ExpressTypes.GENERIC_TYPE";
        } else 
        if (data_name.equals("_ENTITY")) {
		      type_name += "_ENTITY";
//          type_name = "ExpressTypes.GENERIC_ENTITY_TYPE";
				} else {
		      type_name += "_UNSUPPORTED";
				}
      }
   
    
    
    } else {
      System.out.println(
            "XP: constructing type names, not yet supported element type in aggregate: " + rt);
      type_name += "_UNSUPPORTED";
    }

    return type_name;
  }



  String constructBagListSetBoundNames(EVariable_size_aggregation_type vat)
                                throws SdaiException {
    // bounds may be absent.
    // if the lower bound is present, the upper bound may be ? - then I will have one bound only.
    // both bounds may be present. Bounds cannot be negative.   bound 2 >= bound 1
    // so we may have:
    // 1.  _SET_vector;
    // 2.  _SET_2_vector;
    // 3.  _SET_3_10_vector;
    String result = "";

    if (vat.testLower_bound(null)) {
      EBound lb = vat.getLower_bound(null);

      if (lb instanceof EInteger_bound) {
        EInteger_bound ilb = (EInteger_bound) lb;

        if (ilb.testBound_value(null)) {
          int lb_value = ilb.getBound_value(null);
          result += ("_" + lb_value);
        } else {
          // bound set but integer bound unset, strange - internal error
          result += "_1IUNSET";
        }
      } else {
        // may be population dependent bound
       	result += "_1PDB" + extractUniquePDBNumber((EPopulation_dependent_bound)lb);
//        result += "_1PDB";
      }

      if (vat.testUpper_bound(null)) {
        EBound ub = vat.getUpper_bound(null);

        if (ub instanceof EInteger_bound) {
          EInteger_bound iub = (EInteger_bound) ub;

          if (iub.testBound_value(null)) {
            int ub_value = iub.getBound_value(null);
            result += ("_" + ub_value);
          } else {
            // bound set but integer bound unset, strange - internal error
            result += "_2IUNSET";
          }
        } else {
          // may be population dependent bound
	       	result += "_2PDB" + extractUniquePDBNumber((EPopulation_dependent_bound)ub);
//          result += "_2PDB";
        }
      }
    }

    return result;
  }

  String constructArrayBoundNames(EArray_type vat) throws SdaiException {
    // both bounds are mandatory, may be negative, bound1 <= bound2,
    String result = "";

    if (vat.testLower_index(null)) {
      EBound lb = vat.getLower_index(null);

      if (lb instanceof EInteger_bound) {
        EInteger_bound ilb = (EInteger_bound) lb;

        if (ilb.testBound_value(null)) {
          int lb_value = ilb.getBound_value(null);

          if (lb_value < 0) {
            lb_value = -lb_value;
            result += ("_MINUS" + lb_value);
          } else {
            result += ("_" + lb_value);
          }
        } else {
          // bound set but integer bound unset, strange - internal error
          result += "_1IUNSET";
        }
      } else {
        // may be population dependent bound
       	result += "_1PDB" + extractUniquePDBNumber((EPopulation_dependent_bound)lb);
//        result += "_1PDB";
      }
    } else {
      result += "_1UNSET";
    }

    if (vat.testUpper_index(null)) {
      EBound ub = vat.getUpper_index(null);

      if (ub instanceof EInteger_bound) {
        EInteger_bound iub = (EInteger_bound) ub;

        if (iub.testBound_value(null)) {
          int ub_value = iub.getBound_value(null);

          if (ub_value < 0) {
            ub_value = -ub_value;
            result += ("_MINUS" + ub_value);
          } else {
            result += ("_" + ub_value);
          }
        } else {
          // bound set but integer bound unset, strange - internal error
          result += "_2IUNSET";
        }
      } else {
        // may be population dependent bound
       	result += "_2PDB" + extractUniquePDBNumber((EPopulation_dependent_bound)ub);
//        result += "_2PDB";
      }
    } else {
      result += "_2UNSET";
    }

    return result;
  }

  String constructNameWithAggregatePackage(String aggr_prefix, EEntity ee, SdaiModel current_model)
                                    throws SdaiException {
    String a_package = "";
    String a_name = "";

    if (ee instanceof ENamed_type) {
      a_name = ((ENamed_type) ee).getName(null);

      // a_name = a_name.substring(0,1).toUpperCase() + a_name.substring(1).toLowerCase();
    }

    SdaiModel a_model = ee.findEntityInstanceSdaiModel();

    if (a_model != current_model) {
      String a_schema_name = getSchema_definitionFromModel(a_model).getName(null);

      if (a_schema_name.equalsIgnoreCase("Sdai_dictionary_schema")) {
        a_package = "jsdai.dictionary.";
      } else {
        a_package = "jsdai.S" + a_schema_name.substring(0, 1).toUpperCase() + 
                    a_schema_name.substring(1).toLowerCase() + ".";
      }
    }

    //      return a_package;
    // the package must be handled differently.
    // return a_package + aggr_prefix + a_name;
    return "_" + a_name;
  }

  String constructDefinedTypeUnderlyingTypeNameString(EDefined_type rt1)
                                               throws SdaiException {
    String type_name = null;
    boolean name_set = rt1.testName(null);

    if (name_set) {
      return "_" + rt1.getName(null);
    } else {
      return "_UNSET";
    }
  }
}
