gt: 		for (int i = 0; i < methodParamTypes.length; i++) {
context: /**
   * Copyright (C) 2010-2016 Gordon Fraser, Andrea Arcuri and EvoSuite
   * contributors
   *
   * This file is part of EvoSuite.
   *
   * EvoSuite is free software: you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as published
   * by the Free Software Foundation, either version 3.0 of the License, or
   * (at your option) any later version.
   *
   * EvoSuite 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
   * Lesser Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
   */
  package org.evosuite.testcarver.testcase;
  
  import gnu.trove.list.array.TIntArrayList;
  import gnu.trove.map.hash.TIntObjectHashMap;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Method;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.HashSet;
  
  import org.evosuite.TestGenerationContext;
  import org.evosuite.testcarver.capture.CaptureLog;
  import org.evosuite.testcarver.capture.CaptureUtil;
  import org.evosuite.testcase.AssignmentStatement;
  import org.evosuite.testcase.ConstructorStatement;
  import org.evosuite.testcase.DefaultTestCase;
  import org.evosuite.testcase.FieldReference;
  import org.evosuite.testcase.MethodStatement;
  import org.evosuite.testcase.NullStatement;
  import org.evosuite.testcase.PrimitiveStatement;
  import org.evosuite.testcase.TestCase;
  import org.evosuite.testcase.VariableReference;
  import org.evosuite.testcase.VariableReferenceImpl;
  import org.evosuite.utils.GenericConstructor;
  import org.evosuite.utils.GenericField;
  import org.evosuite.utils.GenericMethod;
  
  @Deprecated
  public class TestCaseCodeGenerator {
  	private final CaptureLog log;
  
  	//--- source generation
  
  	public TestCaseCodeGenerator(final CaptureLog log) {
  		if (log == null) {
  			throw new NullPointerException();
  		}
  
  		this.log = log.clone();
  	}
  
  	// FIXME specifying classes here might not be needed anymore, if we only instrument observed classes...
  	public TestCase generateCode(final Class<?>... observedClasses) {
  		if (observedClasses == null || observedClasses.length == 0) {
  			throw new IllegalArgumentException("No observed classes specified");
  		}
  
  		//--- 1. step: extract class names
  		final HashSet<String> observedClassNames = new HashSet<String>();
  		for (int i = 0; i < observedClasses.length; i++) {
  			observedClassNames.add(observedClasses[i].getName());
  		}
  
  		//--- 2. step: get all oids of the instances of the observed classes
  		//    NOTE: They are implicitly sorted by INIT_REC_NO because of the natural object creation order captured by the 
  		//    instrumentation
  		final TIntArrayList targetOIDs = new TIntArrayList();
  		final int numInfoRecs = this.log.oidClassNames.size();
  		for (int i = 0; i < numInfoRecs; i++) {
  			if (observedClassNames.contains(this.log.oidClassNames.get(i))) {
  				targetOIDs.add(this.log.oids.getQuick(i));
  			}
  		}
  
  		//--- 3. step: init compilation unit
  
  		final TestCase testCase = new DefaultTestCase();
  
  		// no invocations on objects of observed classes -> return empty but compilable CompilationUnit
  		if (targetOIDs.isEmpty()) {
  			return testCase;
  		}
  
  		//--- 4. step: generating code starting with OID with lowest log rec no.
  
  		final int numLogRecords = this.log.objectIds.size();
  		int currentOID = targetOIDs.getQuick(0);
  
  		int captureId = -1;
  
  		// TODO knowing last logRecNo for termination criterion belonging to an observed instance would prevent processing unnecessary statements
  		for (int currentRecord = this.log.oidRecMapping.get(currentOID); currentRecord < numLogRecords; currentRecord++) {
  			currentOID = this.log.objectIds.getQuick(currentRecord);
  
  			if (targetOIDs.contains(currentOID)) {
  				this.restorceCodeFromLastPosTo(currentOID, currentRecord, testCase);
  
  				// forward to end of method call sequence
  				captureId = this.log.captureIds.getQuick(currentRecord);
  
  				while (!(this.log.objectIds.getQuick(currentRecord) == currentOID
  				        && this.log.captureIds.getQuick(currentRecord) == captureId && this.log.methodNames.get(currentRecord).equals(CaptureLog.END_CAPTURE_PSEUDO_METHOD))) {
  					currentRecord++;
  				}
  
  				// each method call is considered as object state modification -> so save last object modification
  				
  				log.updateWhereObjectWasInitializedFirst(currentOID, currentRecord);		
  				
  			}
  		}
  
  		return testCase;
  	}
  
  	private void restorceCodeFromLastPosTo(final int oid, final int end, TestCase testCase) {
  		final int oidInfoRecNo = this.log.oidRecMapping.get(oid);
  
  		// start from last OID modification point
  		int currentRecord = log.getRecordIndexOfWhereObjectWasInitializedFirst(oid);
  		
  		if (currentRecord > 0) {
  			// last modification of object happened here
  			// -> we start looking for interesting records after retrieved record
  			currentRecord++;
  		} else {
  			// object new instance statement
  			// -> retrieved loc record no is included
  			currentRecord = -currentRecord;
  		}
  
  		String methodName;
  		int currentOID;
  		int captureId;
  
  		Object[] methodArgs;
  		Integer methodArgOID;
  
  		Integer returnValue;
  		Object returnValueObj;
  
  		for (; currentRecord <= end; currentRecord++) {
  			currentOID = this.log.objectIds.getQuick(currentRecord);
  			returnValueObj = this.log.returnValues.get(currentRecord);
  			returnValue = returnValueObj.equals(CaptureLog.RETURN_TYPE_VOID) ? -1
  			        : (Integer) returnValueObj;
  
  			if (oid == currentOID || returnValue == oid) {
  				methodName = this.log.methodNames.get(currentRecord);
  
  				if (CaptureLog.PLAIN_INIT.equals(methodName)) // e.g. String var = "Hello World";
  				{
  					this.createPlainInitStmt(currentRecord, testCase);
  
  					// TODO: NOT NICE!!! DO IT ALSO FOR PLAIN AND NOT OBSERVED INIT to be consistent
  					captureId = this.log.captureIds.getQuick(currentRecord);
  					while (!(this.log.objectIds.getQuick(currentRecord) == currentOID
  					        && this.log.captureIds.getQuick(currentRecord) == captureId && this.log.methodNames.get(currentRecord).equals(CaptureLog.END_CAPTURE_PSEUDO_METHOD))) {
  						currentRecord++;
  					}
  				} else if (CaptureLog.NOT_OBSERVED_INIT.equals(methodName)) // e.g. Person var = (Person) XSTREAM.fromXML("<xml/>");
  				{
  					this.createUnobservedInitStmt(currentRecord, testCase);
  
  					// TODO: NOT NICE!!! DO IT ALSO FOR PLAIN AND NOT OBSERVED INIT to be consistent
  					captureId = this.log.captureIds.getQuick(currentRecord);
  					while (!(this.log.objectIds.getQuick(currentRecord) == currentOID
  					        && this.log.captureIds.getQuick(currentRecord) == captureId && this.log.methodNames.get(currentRecord).equals(CaptureLog.END_CAPTURE_PSEUDO_METHOD))) {
  						currentRecord++;
  					}
  				} else if (CaptureLog.PUTFIELD.equals(methodName)
  				        || CaptureLog.PUTSTATIC.equals(methodName)
  				        || // field write access such as p.id = id or Person.staticVar = "something"
  				        CaptureLog.GETFIELD.equals(methodName)
  				        || CaptureLog.GETSTATIC.equals(methodName)) // field READ access such as "int a =  p.id" or "String var = Person.staticVar"
  				{
  
  					if (CaptureLog.PUTFIELD.equals(methodName)
  					        || CaptureLog.PUTSTATIC.equals(methodName)) {
  						// a field assignment has always one argument
  						methodArgs = this.log.params.get(currentRecord);
  						methodArgOID = (Integer) methodArgs[0];
  						if (methodArgOID != null && methodArgOID != oid) {
  							// create history of assigned value
  							this.restorceCodeFromLastPosTo(methodArgOID, currentRecord,
  							                               testCase);
  						}
  
  						this.createFieldWriteAccessStmt(currentRecord, testCase);
  					} else {
  						this.createFieldReadAccessStmt(currentRecord, testCase);
  					}
  
  					// TODO: NOT NICE!!! DO IT ALSO FOR PLAIN AND NOT OBSERVED INIT to be consistent
  					captureId = this.log.captureIds.getQuick(currentRecord);
  					while (!(this.log.objectIds.getQuick(currentRecord) == currentOID
  					        && this.log.captureIds.getQuick(currentRecord) == captureId && this.log.methodNames.get(currentRecord).equals(CaptureLog.END_CAPTURE_PSEUDO_METHOD))) {
  						currentRecord++;
  					}
  
  					if (CaptureLog.GETFIELD.equals(methodName)
  					        || CaptureLog.GETSTATIC.equals(methodName)) {
  						// GETFIELD and GETSTATIC should only happen, if we obtain an instance whose creation has not been observed
  						log.updateWhereObjectWasInitializedFirst(currentOID, currentRecord);		
  						
  
  						if (returnValue != -1) {
  							log.updateWhereObjectWasInitializedFirst(returnValue, currentRecord);		
  							
  						}
  					}
  				} else // var0.call(someArg) or Person var0 = new Person()
  				{
  					methodArgs = this.log.params.get(currentRecord);
  
  					for (int i = 0; i < methodArgs.length; i++) {
  						// there can only be OIDs or null
  						methodArgOID = (Integer) methodArgs[i];
  						if (methodArgOID != null && methodArgOID != oid) {
  							this.restorceCodeFromLastPosTo(methodArgOID, currentRecord,
  							                               testCase);
  						}
  					}
  
  					this.createMethodCallStmt(currentRecord, testCase);
  
  					// forward to end of method call sequence
  
  					captureId = this.log.captureIds.getQuick(currentRecord);
  
  					while (!(this.log.objectIds.getQuick(currentRecord) == currentOID
  					        && this.log.captureIds.getQuick(currentRecord) == captureId && this.log.methodNames.get(currentRecord).equals(CaptureLog.END_CAPTURE_PSEUDO_METHOD))) {
  						currentRecord++;
  					}
  
  					// each method call is considered as object state modification -> so save last object modification
  					log.updateWhereObjectWasInitializedFirst(currentOID, currentRecord);		
  					
  
  					if (returnValue != -1) {
  						// if returnValue has not type VOID, mark current log record as record where the return value instance was created
  						// --> if an object is created within an observed method, it would not be semantically correct
  						//     (and impossible to handle properly) to create an extra instance of the return value type outside this method
  						log.updateWhereObjectWasInitializedFirst(returnValue, currentRecord);		
  						
  					}
  
  					// consider each passed argument as being modified at the end of the method call sequence
  					for (int i = 0; i < methodArgs.length; i++) {
  						// there can only be OIDs or null
  						methodArgOID = (Integer) methodArgs[i];
  						if (methodArgOID != null && methodArgOID != oid) {
  							log.updateWhereObjectWasInitializedFirst(methodArgOID, currentRecord);									
  						}
  					}
  				}
  			}
  		}
  	}
  
  	private void createMethodCallStmt(final int logRecNo, final TestCase testCase) {
  		// assumption: all necessary statements are created and there is one variable for reach referenced object
  		final int oid = this.log.objectIds.get(logRecNo);
  		final Object[] methodArgs = this.log.params.get(logRecNo);
  		final String methodName = this.log.methodNames.get(logRecNo);
  
  		final String methodDesc = this.log.descList.get(logRecNo);
  		final org.objectweb.asm.Type[] methodParamTypes = org.objectweb.asm.Type.getArgumentTypes(methodDesc);
  
  		final Class<?>[] methodParamTypeClasses = new Class[methodParamTypes.length];
  