/*
 * $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: 1016210367516 %

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

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


public class X_QueryExpression extends ExpressionNode {
  // public class X_QueryExpression extends SimpleNode {
  String query_variable_id;
  String query_variable_uid;
  String query_variable_scope_id;
  String str_aggregate_source;
  String str_logical_expression;

  public X_QueryExpression(int id) {
    super(id);
  }

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

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

  // ----------------------------- start
  public Object childrenAccept(Compiler2Visitor visitor, Object data)
                        throws SdaiException {
    JavaClass jc = (JavaClass) data;
    String variable_name;
    String variable_declaration;
    String generated_code;
    String le_forwarded_java = "";

    if (children != null) {
      if (jc != null) {
        if (jc.active) {
          // may use more specific types later on.
          // or rather to drop altogether, now we are using Value.
          jc.type_of_operand = JavaClass.T_AGGREGATE;
        }
      }


      /*
      First, the return aggregate may be of  different types, it depends on the aggregate_source.
      In two ways, maybe - is it array, bag, list or set; and also what is the member type.
      Query may be done not only on aggregates of entities but on anything, like SET OF INTEGER, etc.
      Maybe even on generic aggregates - check.
      So my result aggregate, and  also query variable has to be of the corresponding compatible type.
      Or maybe I can use only very general types, first. But maybe better not.
                     
       */

      //         elements = new Vector();
      //         types = new Vector();
      statements = new Vector();
      variable_names = new Vector();
      variable_declarations = new Vector();
      initializing_code = new Vector();

      Vector le_statements = new Vector();
      Vector le_variable_names = new Vector();
      Vector le_variable_declarations = new Vector();
      Vector le_initializing_code = new Vector();
			Vector le_forwarded_stuff = new Vector();
			Vector prev_variable_declarations = new Vector();
			
      boolean le_java_contains_statements = false;

      for (int i = 0; i < children.length; ++i) {
        children[i].jjtAccept(visitor, data);

        if (jc != null) {
          if (jc.active) {
            if (children[i] instanceof X_AggregateSource) {
              // if, for example, aggregate source is represented by an aggregate initializer, do we need to move additional java stuff for
              // aggregate intitializer up out of query? Probably not.
              if (((SimpleNode) children[i]).java_contains_statements) {
                java_contains_statements = true;

                // variable_declaration += "\n" + ((SimpleNode)children[i]).variable_declaration;
                for (int j = 0; j < ((SimpleNode) children[i]).variable_names.size(); j++) {
                  variable_names.add(((SimpleNode) children[i]).variable_names.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).variable_declarations.size(); j++) {
                  variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
//                  prev_variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).statements.size(); j++) {
                  statements.add(((SimpleNode) children[i]).statements.elementAt(j));
                }

                // initializing_code += "\n" + ((SimpleNode)children[i]).initializing_code;
                for (int j = 0; j < ((SimpleNode) children[i]).initializing_code.size(); j++) {
                  initializing_code.add(((SimpleNode) children[i]).initializing_code.elementAt(j));
                }
              }

              str_aggregate_source = jc.generated_java;
            } else if (children[i] instanceof X_QueryLogicalExpression) { // if contains statements
              le_forwarded_java = ((SimpleNode) children[i]).forwarded_java;

              ((SimpleNode) children[i]).forwarded_java = "";
							le_forwarded_stuff = ((SimpleNode) children[i]).forwarded_stuff;

              if (((SimpleNode) children[i]).java_contains_statements) {
                le_java_contains_statements = true;

                // variable_declaration += "\n" + ((SimpleNode)children[i]).variable_declaration;
                for (int j = 0; j < ((SimpleNode) children[i]).variable_names.size(); j++) {
                  le_variable_names.add(((SimpleNode) children[i]).variable_names.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).variable_declarations.size(); j++) {
//                  le_variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
                  le_variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).statements.size(); j++) {
//                  le_statements.add(((SimpleNode) children[i]).statements.elementAt(j));
                  le_statements.add(((SimpleNode) children[i]).statements.elementAt(j));
                }

                // initializing_code += "\n" + ((SimpleNode)children[i]).initializing_code;
                for (int j = 0; j < ((SimpleNode) children[i]).initializing_code.size(); j++) {
                  le_initializing_code.add(((SimpleNode) children[i]).initializing_code.elementAt(j));
                }
              } // if contains statements

              str_logical_expression = jc.generated_java;
            }
          }
        }
      }

      // Let's attempt to put query stuff here:
      // let's use iterator which should work for all kinds of aggregates.
      // the name has to be unique, so let's use the unique identifier
      String iterator_name = "_iter" + (++uid);
      String result_name = "_result" + (++uid);
      String for_index = "_i" + (++uid);
			String aggregate_source_name = "_internal_aggregate_source" + (++uid);
			
      statements.addElement("Value " + aggregate_source_name + " = " + str_aggregate_source + ";");

      //      variable_declaration = "Aggregate " + result_name + " = new Aggregate()";
//      variable_declaration = "Value " + result_name + " = Value.alloc(" + str_aggregate_source + 
//                             ").create();";
      variable_declaration = "Value " + result_name + " = Value.alloc(" + aggregate_source_name + 
                             ").create();";


      //      variable_declarations.addElement(variable_declaration);
      statements.addElement(variable_declaration);


      //      variable_declaration = "SdaiIterator " + iterator_name + " = " + str_aggregate_source + ".createIterator()";
      //         variable_declarations.addElement(variable_declaration);
      //         statements.addElement("while (" + iterator_name + ".next()) {");
			

      statements.addElement("if (" + aggregate_source_name + ".getActualJavaType() != Value.INDETERMINATE) {");

//      statements.addElement("for (int " + for_index + " = 1; " + for_index + " <= " + 
//                            str_aggregate_source + ".getMemberCount(); " + for_index + "++) {");

      statements.addElement("\tfor (int " + for_index + " = 1; " + for_index + " <= " + aggregate_source_name + ".getMemberCount(); " + for_index + "++) {");



      //      statements.addElement("\tValue " + query_variable_id + " = " + str_aggregate_source + ".getByIndex(" + for_index + ");");

//      statements.addElement("\tValue " + query_variable_uid + " = " + str_aggregate_source + 
//                            ".getByIndex(" + for_index + ");");
      statements.addElement("\t\tValue " + query_variable_uid + " = " + aggregate_source_name + ".getByIndex(" + for_index + ");");



      // putting in-front statements from the query_logical_expression child here:
      if (le_java_contains_statements) {
        java_contains_statements = true;

        for (int j = 0; j < le_variable_names.size(); j++) {
          variable_names.add(le_variable_names.elementAt(j));
        }

				boolean if_all_statements_are_string_literals = true;
        for (int j = 0; j < le_statements.size(); j++) {
          // check if each le_statement is a string literal
          // check if the string is something like this:
          // Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "...")
          // no, the string includes more:
      		// 	_elements1.addMember(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "file size"));
      		// here, 1 in _elements1 is not constant, we can check for
      		//  _elements
      		// .addMember(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "
      		// "));
      		// is it safe enough, if all three parts found?
      		// perhaps also check that " occurs only 2 times
      		// and try to check the length of the string, after excluding the variable id number and the string contents

					// so, here are many stupid checks:

/*

					also we want to recognize elemests consisting of two or three strings:
					'a' + 'b'
					'a' + 'b' + 'c'
					as such string combinations also occur in real schemas, especially in such combinations as
					'schema_name' + 'entity_name'
					'schem_name' + 'entity_name' + 'attribute_name'
					Not sure if such combinations are encountered often in aggregate initializers, though,
					especially the 3 part ones, here is a real two part one:
					
	 wr1: SIZEOF ( QUERY ( ri <* representation_item | NOT (
     type_check_function ( ri , ['AUTOMOTIVE_DESIGN.' +
     'COMPOUND_REPRESENTATION_ITEM' , 'AUTOMOTIVE_DESIGN.' +
     'DESCRIPTIVE_REPRESENTATION_ITEM' , 'AUTOMOTIVE_DESIGN.' +
     'KINEMATIC_PATH' , 'AUTOMOTIVE_DESIGN.' +
     'MEASURE_REPRESENTATION_ITEM' , 'AUTOMOTIVE_DESIGN.' +
     'REP_ITEM_GROUP' , 'AUTOMOTIVE_DESIGN.' +
     'VALUE_REPRESENTATION_ITEM'] , 3 ) ) ) ) =  0;					

				here is an example of 3-part one, but this example is not with aggregate initializer,
				just a 3-part string:
				
 wr1: SIZEOF ( QUERY ( ent <* geometric_representation_item |
     SIZEOF ( QUERY ( mlaa <* USEDIN ( ent ,
     'AUTOMOTIVE_DESIGN.' +
     'MULTI_LANGUAGE_ATTRIBUTE_ASSIGNMENT.' + 'ITEMS' ) | (
     mlaa.attribute_name<>'name' ) ) ) >0 ) ) =  0;
				
	  however, this case perhaps should be also supported.
	 here, it is is usedin and not in the query logical expression but in aggregate_source,
	 therefore it is not even in the loop, but it is still in the loop of another query, because the queries are nested,
	 it could be moveed out in front of the loop, but such an implementation requires to handle more than a query.
	 It may be quite complicated to implement				

	 here are generated cases for 1, 2, and 3 string combinations:
	 
								_elements23.addMember(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "page count"));

								_elements23.addMember(_context, Value.alloc().addOrUnionOrConcatenate(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "file size"), Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "whatever")));

								_elements38.addMember(_context, Value.alloc().addOrUnionOrConcatenate(_context, Value.alloc().addOrUnionOrConcatenate(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "file size"), Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "something")), Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "nothing")));


	 
   
   what is in common here? perhaps a generalized approach could be implemented to recognize them?
   But perhaps we really need only to add the 'a' + 'b' case, the 3-nary cases are not sure even to occur, and more than 3, probably never occur,
   unless '.'  are handled separately, i.e., I could invent such test cases, but perhaps not in real schemas.
   Let's format them to see them more clearly:
   
   
								_elements23.addMember(
									_context, 
									Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "page count")
								);

								_elements23.addMember(
									_context, 
									Value.alloc().addOrUnionOrConcatenate(
										_context, 
										Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "file size"), 
										Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "whatever")
									)
								);

								_elements38.addMember(
									_context, 
									Value.alloc().addOrUnionOrConcatenate(
										_context, 
										Value.alloc().addOrUnionOrConcatenate(
											_context, 
											Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "file size"), 
											Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "something")
										), 
										Value.alloc(ExpressTypes.STRING_TYPE).set(_context, "nothing")
									)
								);


   
	  ---------------------------------------------------------

								_elements23.addMember(
									_context,
									_string_literal_expression_
								);

								_elements23.addMember(
									_context, 
									Value.alloc().addOrUnionOrConcatenate(
										_context, 
										_string_literal_expression_, 
										_string_literal_expression_ 
									)
								);

								_elements38.addMember(
									_context, 
									Value.alloc().addOrUnionOrConcatenate(
										_context, 
										Value.alloc().addOrUnionOrConcatenate(
											_context, 
											_string_literal_expression_, 
											_string_literal_expression_ 
										), 
										_string_literal_expression_ 
									)
								);


--------------------------------

								_elements23.addMember(
									_context,
									_string_literal_expression_
								);

								_elements23.addMember(
									_context, 
									_a_plus_b_expression_
								);

								_elements38.addMember(
									_context, 
									Value.alloc().addOrUnionOrConcatenate(
										_context, 
										_a_plus_b_expression_,
										_string_literal_expression_ 
									)
								);



-------


	_elements23.addMember(_context, _string_literal_expression_);

	_elements23.addMember(_context, _a_plus_b_expression_);

	_elements38.addMember(_context, Value.alloc().addOrUnionOrConcatenate(_context, _a_plus_b_expression_, _string_literal_expression_));


### here, 

_string_literal_ = "something"

_string_literal_expression_ = Value.alloc(ExpressTypes.STRING_TYPE).set(_context, _string_literal_)
	  
_a_plus_b_expression_ = Value.alloc().addOrUnionOrConcatenate(_context, _string_literal_expression_, _string_literal_expression_)
	 

for identification purposes, we could make a copy, and then handle everything literally: 
replace "something" and other string literals by _string_literal_
that would allow to handle comparisons at once, not fragment-by-fragment, etc:
1)  replace each occurence of "...." by _string_literal_
2) replace each occurence of 	Value.alloc(ExpressTypes.STRING_TYPE).set(_context, _string_literal_) by _string_literal_expression_
3) replace each occurence of  Value.alloc().addOrUnionOrConcatenate(_context, _string_literal_expression_, _string_literal_expression_)
by _a_plus_b_expression_

then we only need to check if the resulting expression is:
1) either:
	_elements23.addMember(_context, _string_literal_expression_);
	or:
	_elements23.addMember(_context, _a_plus_b_expression_);
	or:
	_elements38.addMember(_context, Value.alloc().addOrUnionOrConcatenate(_context, _a_plus_b_expression_, _string_literal_expression_));


*/
			
					String current_statement = (String) le_statements.elementAt(j);
//System.out.println("current statement: " + current_statement);		
					String current_statement_string_litarals_replaced = replace_string_literals(current_statement);
//System.out.println("literals replaced: " + current_statement_string_litarals_replaced);		
					String current_statement_string_literal_expressions_replaced = replace_string_literal_expressions(current_statement_string_litarals_replaced);
//System.out.println("expressions replaced: " + current_statement_string_literal_expressions_replaced);		
					String current_statement_a_plus_b_replaced = replace_a_plus_b(current_statement_string_literal_expressions_replaced);
//System.out.println("a + b replaced: " + current_statement_a_plus_b_replaced);		
					String current_statement_a_plus_b_plus_c_replaced = replace_a_plus_b_plus_c(current_statement_a_plus_b_replaced);
					// we further make all the checks on current_statement_a_plus_b_replaced
//System.out.println("a + b + c replaced: " + current_statement_a_plus_b_plus_c_replaced);		

// System.out.println("statement: " + current_statement + ", length: "  + current_statement.length());        
        	if (!current_statement_a_plus_b_plus_c_replaced.startsWith("_elements")) {
        		if_all_statements_are_string_literals = false;
        		break;
        	}
        	if (!(current_statement_a_plus_b_plus_c_replaced.endsWith(".addMember(_context, _string_literal_expression_);") ||
        			current_statement_a_plus_b_plus_c_replaced.endsWith(".addMember(_context, _a_plus_b_expression_);") ||
        			current_statement_a_plus_b_plus_c_replaced.endsWith(".addMember(_context, _a_plus_b_plus_c_expression_);")
        			)) {
        		if_all_statements_are_string_literals = false;
        		break;
  				}
				  
  
 // old implementation with only one string literal, replaced by new one which allows string_literal_1 + string_literal_2 
 // the new implementation currently does not include checks based on the string length, in practice, perhaps not needed
 /* 
  
        	if (!current_statement.endsWith("\"));")) {
        		if_all_statements_are_string_literals = false;
        		break;
        	}
					int index_id_start = 9;
					int index_id_end = current_statement.indexOf(".addMember(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, \"");
        	int index_quote_1 = index_id_end +  73;
        	int index_quote_2 = current_statement.indexOf("\"));");
        	String string_substring = current_statement.substring(index_quote_1+1, index_quote_2);
        	int index_quote_inside_string = string_substring.indexOf("\"");
// System.out.println("index 1: " + index_quote_1 + ", index 2: " + index_quote_2 + ", substring: " + string_substring + ", index 3: " + index_quote_inside_string);        

        	if (index_id_end < 0) {
        		if_all_statements_are_string_literals = false;
        		break;
        	}
					// already checked with endsWith - no need for this! Or rather for endsWith, as this index is needed					
					if (index_quote_2 < 0) {
        		if_all_statements_are_string_literals = false;
        		break;
					}
					if (index_quote_inside_string >= 0) {
        		if_all_statements_are_string_literals = false;
        		break;
					}
					// let's calculate the length of the statement string:
					// int total_length = _elements + 
					// 										id_length + 
					//										.addMember(_context, Value.alloc(ExpressTypes.STRING_TYPE).set(_context, " +
					// 										string_length + 
					//                    "));

       		//   
       
	        int total_length = 9 + index_id_end - index_id_start + 74 + string_substring.length() + 4;
	        if (total_length != current_statement.length()) {
        		if_all_statements_are_string_literals = false;
        		break;
	     
	     
	        }

*/


        }  
//        System.out.println("string literal: " + if_all_statements_are_string_literals);
        
        


        for (int j = 0; j < le_variable_declarations.size(); j++) {

// System.out.println("adding declaration: " + le_variable_declarations.elementAt(j));

					/*
						this change fixes the bug, when in query logical expression an aggregate with direct aggregate initializers is used,
						and the members are added in the loop multiple times instead of one time.
						This fix puts the creation of the aggregate itself into the loop.
						it is ok for variable expressions in aggregate initializers, but for constant expressions a different solution could be used:
						to move those initializations in front of the loop as well.
						But what about mixed cases of variable and constant expressions?
						Then perhaps set methods can be used, together with additional checks generated.
						
						NOTE: this solution has to be tested - it may have bad side effects, because all previous variable declarations in logical expression 
						now go together with statements
						
						
						one simple optimization:
						to run the le_statements and check them all, if they are  string literal type constant expressions,
						if so, add BOTH le_variable_declarations and le_statements to variable_declarations,
						if not - to statements.
						This is a potentially dangerous solution, but perhaps safe because, if at least one statement is not a string literal,
						then no statements are moved in front of the loop
						
						
						
					*/

					if (if_all_statements_are_string_literals) {
						// for this special case of constant expressions, move everything in front of the loop, both creation and adding members
	          variable_declarations.add(le_variable_declarations.elementAt(j));
					} else {
						// assume that it might be a variable expression, leave everything inside the loop, both creation and adding members
	          statements.add(le_variable_declarations.elementAt(j));
					}
        }

        for (int j = 0; j < le_statements.size(); j++) {
					if (if_all_statements_are_string_literals) {
	          variable_declarations.add(le_statements.elementAt(j));
					} else {
	          statements.add(le_statements.elementAt(j));
					}
        }

        for (int j = 0; j < le_initializing_code.size(); j++) {
          initializing_code.add(le_initializing_code.elementAt(j));
        }
      }

//			 for (int j = 0; j < le_forwarded_stuff.size(); j++) {
//          System.out.println("<<>>: " + (String)le_forwarded_stuff.elementAt(j));
//			 }


			String le_forwarded_current = le_forwarded_java;
//System.out.println("lf current statement: " + le_forwarded_current);		
			String le_forwarded_string_litarals_replaced = replace_string_literals(le_forwarded_current);
//System.out.println("lf literals replaced: " + le_forwarded_string_litarals_replaced);		
					String le_forwarded_string_literal_expressions_replaced = replace_string_literal_expressions(le_forwarded_string_litarals_replaced);
//System.out.println("lf expressions replaced: " + le_forwarded_string_literal_expressions_replaced);		
					String le_forwarded_a_plus_b_replaced = replace_a_plus_b(le_forwarded_string_literal_expressions_replaced);
//System.out.println("lf a + b replaced: " + le_forwarded_a_plus_b_replaced);		
					String le_forwarded_a_plus_b_plus_c_replaced = replace_a_plus_b_plus_c(le_forwarded_a_plus_b_replaced);
					// we further make all the checks on current_statement_a_plus_b_replaced
//System.out.println("a + b + c replaced: " + le_forwarded_a_plus_b_plus_c_replaced);		

			
			boolean const_string_expressions = true;


//System.out.println("final input: " + le_forwarded_a_plus_b_plus_c_replaced);		
			StringReader insr = new StringReader(le_forwarded_a_plus_b_plus_c_replaced);
			BufferedReader inbr = new BufferedReader(insr);
			String lineItem;
//System.out.println("ins: " + insr);
//System.out.println("in: " + inbr);
//System.out.println("is ready: " + inbr.ready());

//			while ((lineItem = in.readLine()) != null) {
//				lineItem = in.readLine();
			for (;;) {
				// inbr.ready();
				lineItem = readLine(inbr);
				if (lineItem == null) {
//System.out.println("breaking 2");
					break;
				}
				lineItem = lineItem.trim();
				if (lineItem.equals("")) {
					continue;
				}
//System.out.println("lineItem: " + lineItem);

		  	if (
		  				!((lineItem.startsWith("Value _elements") &&
		  				lineItem.endsWith(" = Value.alloc(ExpressTypes.AGGREGATE_GENERIC_TYPE).create();"))
							||
							(
								lineItem.startsWith("_elements") &&
								(
									lineItem.endsWith(".addMember(_context, _string_literal_expression_);")  ||
									lineItem.endsWith(".addMember(_context, _a_plus_b_expression_);")        ||
									lineItem.endsWith(".addMember(_context, _a_plus_b_plus_c_expression_);")
								)
							))


		  		 ) {
		  			const_string_expressions = false;
//System.out.println("breaking");
		  			break;
		  		}
		  	}
				close(inbr);


			if (const_string_expressions) {
	    	variable_declarations.add(le_forwarded_java);
			} else {
      	statements.addElement(le_forwarded_java);
			}
//System.out.println("adding forwarded: " + le_forwarded_java);
//      statements.addElement("\tif (" + str_logical_expression + ") {");
      statements.addElement("\t\tif (" + str_logical_expression + ") {");


      //      statements.addElement("\t\t" + result_name + ".addMember(_context, " + query_variable_id + ");");
//      statements.addElement("\t\t" + result_name + ".addMember(_context, " + query_variable_uid + ");");
      statements.addElement("\t\t\t" + result_name + ".addMember(_context, " + query_variable_uid + ");");
//      statements.addElement("\t}");

      statements.addElement("\t\t} else");
			statements.addElement("\t\tif ("+ aggregate_source_name + ".getDeclaredType() instanceof jsdai.dictionary.EArray_type) {");
      statements.addElement("\t\t\t" + query_variable_uid + ".unset();");
      statements.addElement("\t\t\t" + result_name + ".addMember(_context, " + query_variable_uid + ");");


      statements.addElement("\t\t}");
//      statements.addElement("}");
      statements.addElement("\t}");

      statements.addElement("} else {");
      statements.addElement("\t" + result_name + ".unset();");
      statements.addElement("}");

      java_contains_statements = true;

      if (jc != null) {
        if (jc.active) {
          jc.generated_java = result_name;
        }
      }
    }

    return data;
  }

  //----------------------------- end
  public Object childrenAccept_old(Compiler2Visitor visitor, Object data)
                            throws SdaiException {
    JavaClass jc = (JavaClass) data;
    String variable_name;
    String variable_declaration;
    String generated_code;

    if (children != null) {
      if (jc != null) {
        if (jc.active) {
          // may use more specific types later on.
          jc.type_of_operand = JavaClass.T_AGGREGATE;
        }
      }


      /*
      First, the return aggregate may be of  different types, it depends on the aggregate_source.
      In two ways, maybe - is it array, bag, list or set; and also what is the member type.
      Query may be done not only on aggregates of entities but on anything, like SET OF INTEGER, etc.
      Maybe even on generic aggregates - check.
      So my result aggregate, and  also query variable has to be of the corresponding compatible type.
      Or maybe I can use only very general types, first. But maybe better not.
                     
       */

      //         elements = new Vector();
      //         types = new Vector();
      statements = new Vector();
      variable_names = new Vector();
      variable_declarations = new Vector();
      initializing_code = new Vector();

      for (int i = 0; i < children.length; ++i) {
        children[i].jjtAccept(visitor, data);

        if (jc != null) {
          if (jc.active) {
            if (children[i] instanceof X_AggregateSource) {
              // if, for example, aggregate source is represented by an aggregate initializer, do we need to move additional java stuff for
              // aggregate intitializer up out of query? Probably not.
              if (((SimpleNode) children[i]).java_contains_statements) {
                java_contains_statements = true;

                // variable_declaration += "\n" + ((SimpleNode)children[i]).variable_declaration;
                for (int j = 0; j < ((SimpleNode) children[i]).variable_names.size(); j++) {
                  variable_names.add(((SimpleNode) children[i]).variable_names.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).variable_declarations.size(); j++) {
                  variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).statements.size(); j++) {
                  statements.add(((SimpleNode) children[i]).statements.elementAt(j));
                }

                // initializing_code += "\n" + ((SimpleNode)children[i]).initializing_code;
                for (int j = 0; j < ((SimpleNode) children[i]).initializing_code.size(); j++) {
                  initializing_code.add(((SimpleNode) children[i]).initializing_code.elementAt(j));
                }
              }

              str_aggregate_source = jc.generated_java;
            } else if (children[i] instanceof X_QueryLogicalExpression) { // if contains statements

              if (((SimpleNode) children[i]).java_contains_statements) {
                java_contains_statements = true;

                // variable_declaration += "\n" + ((SimpleNode)children[i]).variable_declaration;
                for (int j = 0; j < ((SimpleNode) children[i]).variable_names.size(); j++) {
                  variable_names.add(((SimpleNode) children[i]).variable_names.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).variable_declarations.size(); j++) {
                  variable_declarations.add(((SimpleNode) children[i]).variable_declarations.elementAt(j));
                }

                for (int j = 0; j < ((SimpleNode) children[i]).statements.size(); j++) {
                  statements.add(((SimpleNode) children[i]).statements.elementAt(j));
                }

                // initializing_code += "\n" + ((SimpleNode)children[i]).initializing_code;
                for (int j = 0; j < ((SimpleNode) children[i]).initializing_code.size(); j++) {
                  initializing_code.add(((SimpleNode) children[i]).initializing_code.elementAt(j));
                }
              } // if contains statements

              str_logical_expression = jc.generated_java;
            }
          }
        }
      }

      // Let's attempt to put query stuff here:
      // let's use iterator which should work for all kinds of aggregates.
      // the name has to be unique, so let's use the unique identifier
      String iterator_name = "_iter" + (++uid);
      String result_name = "_result" + (++uid);
      String for_index = "_i" + (++uid);


      //      variable_declaration = "Aggregate " + result_name + " = new Aggregate()";
      variable_declaration = "Value " + result_name + " = Value.alloc(" + str_aggregate_source + 
                             ").create();";
      variable_declarations.addElement(variable_declaration);


      //      variable_declaration = "SdaiIterator " + iterator_name + " = " + str_aggregate_source + ".createIterator()";
      //         variable_declarations.addElement(variable_declaration);
      //         statements.addElement("while (" + iterator_name + ".next()) {");
      statements.addElement("for (int " + for_index + " = 1; " + for_index + " <= " + 
                            result_name + ".getMemberCount(); " + for_index + "++) {");


      //      statements.addElement("\tValue " + query_variable_id + " = " + result_name + ".getByIndex(" + for_index + ");");
      statements.addElement("\tValue " + query_variable_uid + " = " + result_name + 
                            ".getByIndex(" + for_index + ");");
      statements.addElement("\tif (" + str_logical_expression + ") {");


      //      statements.addElement("\t\t" + result_name + ".addMember(_context, " + query_variable_id + ");");
      statements.addElement("\t\t" + result_name + ".addMember(_context, " + query_variable_uid + ");");
      statements.addElement("\t}");
      statements.addElement("}");
      java_contains_statements = true;

      if (jc != null) {
        if (jc.active) {
          jc.generated_java = result_name;
        }
      }

      //      for (int i = 0; i < children.length; ++i) {
      //        children[i].jjtAccept(visitor, data);
      //            if (jc != null) {
      //               if (jc.active) {
      //                  elements.addElement(jc.generated_java);
      //                  types.addElement(new Integer(jc.type_of_operand));
      //                  jc.generated_java = "";
      //               }
      //            }
      //     }
      // checking the types of elements.
      // if all types are strings, then A_string is generated, and addUrdered is generated in the loop.
      // other types have to be supported as well, in the case of different types, maybe AEntity, or error message
      //       boolean one_type = true;
      //       int all_types = 0;
      //       for (int i = 0; i < types.size(); i++) {
      //          int a_type = ((Integer)types.elementAt(i)).intValue();
      //          if (all_types == 0) all_types = a_type;
      //          if (all_types != a_type) {
      //             one_type = false;
      //             break;
      //          }
      //       }
      //

      /*
                   
             if (one_type) {
                  uid++;
                  current_uid = uid;
                  String var_name = "_elements" + uid;
                  variable_names.addElement(var_name);
                  java_contains_statements = true;
                if (all_types == JavaClass.T_STRING) {
                     jc.type_of_operand = JavaClass.T_AGGREGATE;
                     variable_declaration = "A_string " + var_name + " = new A_string()";
                     variable_declarations.addElement(variable_declaration);
                     for (int i = 0; i < elements.size(); i ++) {
                        statements.addElement(var_name + ".addUnordered(" + (String)elements.elementAt(i) + ");");
                     }
                } else
                if (all_types == JavaClass.T_INTEGER) { // we can use strings here, or Integer, but it may be not needed
                     jc.type_of_operand = JavaClass.T_AGGREGATE;
                     variable_declaration = "A_string " + var_name + " = new A_integer()";
                     variable_declarations.addElement(variable_declaration);
                     for (int i = 0; i < elements.size(); i ++) {
                        statements.addElement(var_name + ".addUnordered(" + new Integer((String)elements.elementAt(i)) + ");");
                     }
                }
                generated_code = "initializeAggregate(" + var_name + ")";
                  initializing_code.addElement(generated_code);
                  if (jc != null) {
                     if (jc.active) {
                        jc.generated_java = generated_code;
                       jc.type_of_operand = JavaClass.T_AGGREGATE;
                   }
                }
             }
                
       */
    }

    return data;
  }

	/*
		replace each occurence of a  string litaral  "...." by "_string_literal_"
	*/
	String replace_string_literals(String original_str) {
		String result;
		String intermediate = original_str;
		int quote_1;
		int quote_2;
		for (;;) {
			quote_1 = intermediate.indexOf('\"');
			quote_2 = intermediate.indexOf('\"', quote_1 + 1);
// System.out.println("<1> 1: " + quote_1 + ", 2: " + quote_2);
			if ((quote_1 > 0) && (quote_2 > quote_1)) {
				String temp = intermediate.substring(quote_1+1,quote_2);
//System.out.println("temp: " + temp);
				if (temp.equals("*.")) {				
					// if * then leave it as it is, we we'll deal with this case later on in string_literal_expression
					String intermediate2 = intermediate.substring(0,quote_1) + "_star_dot_" + intermediate.substring(quote_2 + 1);
					intermediate = intermediate2;
				} else {
					String intermediate2 = intermediate.substring(0,quote_1) + "_string_literal_" + intermediate.substring(quote_2 + 1);
					intermediate = intermediate2;
				}
			} else {
				break;
			}
			// quote_3 = original_str.indexOf('\"', quote_2);
			// if (quote_3 > 0) {
			//	return original_str;
			// }
		}
		result = intermediate;
//System.out.println("replacing string literal: " + result);		
		return result;
	}

	/*
			replace each occurence of 	
			Value.alloc(ExpressTypes.STRING_TYPE).set(_context, _string_literal_) 
			by 
			"_string_literal_expression_"
		
	*/		
	String replace_string_literal_expressions(String original_str) {
		String result;
		String intermediate = original_str;
		for (;;) {
			int index =  intermediate.indexOf("Value.alloc(ExpressTypes.STRING_TYPE).set(_context, _string_literal_)");
			int index2 = intermediate.indexOf("Value.alloc(ExpressTypes.STRING_TYPE).set(_context, _star_dot_, _string_literal_)");
			if (index > 0 && index2 > 0) {
				if (index2 < index) {
					intermediate = intermediate.substring(0,index2) + "_string_literal_expression_" + intermediate.substring(index2 + 81);
				} else {
					intermediate = intermediate.substring(0,index) + "_string_literal_expression_" + intermediate.substring(index + 69);
				}
			} else {
				if (index > 0) {
					intermediate = intermediate.substring(0,index) + "_string_literal_expression_" + intermediate.substring(index + 69);
				} else 
				if (index2 > 0) {
					intermediate = intermediate.substring(0,index2) + "_string_literal_expression_" + intermediate.substring(index2 + 81);
				} else {
					break;
				}
			}
		}			
		result = intermediate;
//System.out.println("replacing string literal expression: " + result);		
		return result;
		
	}

	/*
			replace each occurence of 	
			Value.alloc().addOrUnionOrConcatenate(_context, _string_literal_expression_, _string_literal_expression_)
			by 
			"_a_plus_b_expression_"
		
	*/		
	String replace_a_plus_b(String original_str) {
		String result;
		String intermediate = original_str;
		for (;;) {
			int index =  intermediate.indexOf("Value.alloc().addOrUnionOrConcatenate(_context, _string_literal_expression_, _string_literal_expression_)");
			if (index > 0) {
				intermediate = intermediate.substring(0,index) + "_a_plus_b_expression_" + intermediate.substring(index + 105);
			} else {
				break;
			}
		}			
		result = intermediate;
//System.out.println("replacing a + b expression: " + result);		
		return result;
		
	}


/*
			replace each occurence of 	
			Value.alloc().addOrUnionOrConcatenate(_context, _a_plus_b_expression_, _string_literal_expression_)			
			by 
			"_a_plus_b_plus_c_expression_"
		
	*/		
	String replace_a_plus_b_plus_c(String original_str) {
		String result;
		String intermediate = original_str;
		for (;;) {
			int index =  intermediate.indexOf("Value.alloc().addOrUnionOrConcatenate(_context, _a_plus_b_expression_, _string_literal_expression_)");
			if (index > 0) {
				intermediate = intermediate.substring(0,index) + "_a_plus_b_plus_c_expression_" + intermediate.substring(index + 99);
			} else {
				break;
			}
		}			
		result = intermediate;
//System.out.println("replacing a + b expression: " + result);		
		return result;
		
	}


	static String readLine(BufferedReader bufferedReader) {
   try 
   {
   		return bufferedReader.readLine( );
   } catch(IOException e) {
   }
   return null;		
	}


	static void close(BufferedReader bufferedReader) {
    try {
        bufferedReader.close( );
    }
    catch(IOException e) { }
	}


}
