/*
 * This file is covered by the terms of the Common Public License v1.0.
 *
 * Copyright (c) SZEDER Gábor
 *
 * Parts of this software were developed within the JEOPARD research
 * project, which received funding from the European Union's Seventh
 * Framework Programme under grant agreement No. 216682.
 */

package de.fzi.cjunit.jpf.util;

import gov.nasa.jpf.jvm.ClassInfo;
import gov.nasa.jpf.jvm.DynamicArea;
import gov.nasa.jpf.jvm.ElementInfo;
import gov.nasa.jpf.jvm.FieldInfo;

import static de.fzi.cjunit.internal.util.LineSeparator.lineSeparator;


public class ElementInfoWrapper {

	ElementInfo elementInfo;

	public ElementInfoWrapper(ElementInfo elementInfo,
			Class<?> expectedClass) {
		String className = elementInfo.getClassInfo().getName();
		if (!className.equals(expectedClass.getName())) {
			String gripe = "ElementInfo type mismatch:"
				+ lineSeparator + "expected: "
				+ expectedClass.getName() + lineSeparator
				+ "got: " + className;
			throw new RuntimeException(gripe);
		}

		this.elementInfo = elementInfo;
	}

	public ElementInfo getWrappedElementInfo() {
		return elementInfo;
	}

	public FieldInfo getFieldInfo(String fieldName) {
		ClassInfo classInfo = elementInfo.getClassInfo();
		while (classInfo != null) {
			FieldInfo fieldInfo = classInfo.getDeclaredInstanceField(
					fieldName);
			if (fieldInfo != null) {
				return fieldInfo;
			}
			classInfo = classInfo.getSuperClass();
		}
		throw new RuntimeException(
				"No such field: " + fieldName);
	}

	public int getReferenceValueForField(String fieldName) {
		FieldInfo fieldInfo = getFieldInfo(fieldName);
		final int[] values = elementInfo.getFields().dumpRawValues();
		return values[fieldInfo.getStorageOffset()];
	}

	public ElementInfo getElementInfoForField(String fieldName) {
		int refVal = getReferenceValueForField(fieldName);
		return DynamicArea.getHeap().get(refVal);
	}

	public String getStringField(String fieldName) {
		return elementInfo.getStringField(fieldName);
	}

	public int getIntField(String fieldName) {
		return elementInfo.getIntField(fieldName);
	}

	public int getArrayLength(String fieldName) {
		ElementInfo arrayElementInfo
				= getElementInfoForField(fieldName);
		if (!arrayElementInfo.isArray()) {
			throw new RuntimeException(
					"Not an array: " + fieldName);
		}
		return arrayElementInfo.arrayLength();
	}

	public ElementInfo[] getReferenceArray(String fieldName) {
		ElementInfo arrayElementInfo
				= getElementInfoForField(fieldName);
		if (!arrayElementInfo.getClassInfo().isReferenceArray()) {
			throw new RuntimeException(
					"Not a reference array: " + fieldName);
		}

		ElementInfo[] array = new ElementInfo[
				arrayElementInfo.arrayLength()];
		for (int i = 0; i < array.length; i++) {
			int ref = arrayElementInfo.getFields().dumpRawValues()[i];
			array[i] = DynamicArea.getHeap().get(ref);
		}

		return array;
	}
}

@@ -704,27 +704,13 @@
 %7B%0A%09%09
-String className = 
+if (!
 elem
@@ -736,42 +736,20 @@
 o().
-getName();%0A%09%09if (!className.equals
+isInstanceOf
 (exp
@@ -921,17 +921,44 @@
 %22 + 
-class
+elementInfo.getClassInfo().get
 Name
+()
 ;%0A%09%09

allow wrapping subclasses