// vrmlNodeからSphereオブジェクトを作る
CX3DSphereNode::CX3DSphereNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);
	
	// テンポラリノード(フィールド探査用)
	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "Sphere")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "solid") == 0)
						{
							m_solid.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "radius") == 0)
						{
							m_radius.setValue(data);
						}

						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}
CVRMLFieldDataFactory::CVRMLFieldDataFactory()
{
	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju)
	{
		fprintf(stderr, "CJNIUtil not initialized [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	JNIEnv *env = ju->env();

	// ************************************************************
	//   CAUTION: argument of FindClass() should be paid attention
	// ************************************************************
	// Error
	// jclass c = env->FindClass("org.web3d.vrml.nodes.VRMLFieldData");

	// The following line is OK
	jclass c = env->FindClass("org/web3d/vrml/nodes/VRMLFieldData");
	if (!c)
	{
		fprintf(stderr, "cannot find VRMLFieldData class\n");
		exit(1);
	}

	m_fid_dataType          = env->GetFieldID(c, "dataType",          "S");
	m_fid_booleanValue      = env->GetFieldID(c, "booleanValue",      "Z");	// "Z" = boolean
	m_fid_intValue          = env->GetFieldID(c, "intValue",          "I");
	m_fid_longValue         = env->GetFieldID(c, "longValue",         "J");	// "J" = long
	m_fid_floatValue        = env->GetFieldID(c, "floatValue",        "F");
	m_fid_doubleValue       = env->GetFieldID(c, "doubleValue",       "D");
	m_fid_stringValue       = env->GetFieldID(c, "stringValue",       "Ljava/lang/String;");
	m_fid_nodeValue         = env->GetFieldID(c, "nodeValue",         "Lorg/web3d/vrml/lang/VRMLNode;");
	m_fid_booleanArrayValue = env->GetFieldID(c, "booleanArrayValue", "[Z");
	m_fid_intArrayValue     = env->GetFieldID(c, "intArrayValue",     "[I");
	m_fid_longArrayValue    = env->GetFieldID(c, "longArrayValue",    "[J");
	m_fid_floatArrayValue   = env->GetFieldID(c, "floatArrayValue",   "[F");
	m_fid_doubleArrayValue  = env->GetFieldID(c, "doubleArrayValue",  "[D");
	m_fid_stringArrayValue  = env->GetFieldID(c, "stringArrayValue",  "[Ljava/lang/String;");
	m_fid_nodeArrayValue    = env->GetFieldID(c, "nodeArrayValue",    "[Lorg/web3d/vrml/lang/VRMLNode;");
}
// vrmlNodeからOpenHRPSegmentオブジェクトを作る
CX3DOpenHRPSegmentNode::CX3DOpenHRPSegmentNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);

	// テンポラリノード(フィールド探査用)
	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "Segment")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "children") == 0)
						{
							m_children.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "name") == 0)
						{
							m_name.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "coord") == 0)
						{
							m_coord.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "centerOfMass") == 0)
						{
							m_centerOfMass.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "displacers") == 0)
						{
							m_displacers.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "mass") == 0)
						{
							m_mass.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "momentsOfInertia") == 0)
						{
							m_momentsOfInertia.setValue(data);
						}

						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}
CVRMLFieldData *CVRMLFieldDataFactory::createField(jobject vrmlFieldData)
{
	CVRMLFieldData *data = NULL;

	CJNIUtil *ju = CJNIUtil::getUtil();
	JNIEnv *env = ju->env();

	short dataType = env->GetShortField(vrmlFieldData, m_fid_dataType);

	switch (dataType)
	{
	case BOOLEAN_DATA:
		{
			jboolean value = env->GetBooleanField(vrmlFieldData, m_fid_booleanValue);
			data = new CVRMLBooleanData((value == JNI_TRUE) ? true : false);
		}
		break;

	case INT_DATA:
		{
			jint value = env->GetIntField(vrmlFieldData, m_fid_intValue);
			data = new CVRMLIntData((int)value);
		}
		break;

	case LONG_DATA:
		{
			jlong value = env->GetLongField(vrmlFieldData, m_fid_longValue);
			data = new CVRMLLongData(value);
		}
		break;

	case FLOAT_DATA:
		{
			jfloat value = env->GetFloatField(vrmlFieldData, m_fid_floatValue);
			data = new CVRMLFloatData(value);
		}
		break;

	case DOUBLE_DATA:
		{
			jdouble value = env->GetDoubleField(vrmlFieldData, m_fid_doubleValue);
			data = new CVRMLDoubleData(value);
		}
		break;

	case STRING_DATA:
		{
			jobject value = env->GetObjectField(vrmlFieldData, m_fid_stringValue);

			jclass stringClass = env->FindClass("java/lang/String");
			if (!stringClass) {
				fprintf(stderr, "cannot find String Class\n");
				exit(1);
			}

			if (value) {
				if (env->IsInstanceOf(value, stringClass)) {
					jstring str = (jstring)value;

					jboolean isCopy;
					const char *utf8Chars = env->GetStringUTFChars(str, &isCopy);

					data = new CVRMLStringData(utf8Chars);

					if (isCopy == JNI_TRUE) {
						env->ReleaseStringUTFChars(str, utf8Chars);
					}
				}
			}
			else {
				// Added on 2009-02-23 by msi
				// Let the name empty if the pointer is NULL
				data = new CVRMLStringData("");
			}
		}
		break;

	case NODE_DATA:
		{
			jobject value = env->GetObjectField(vrmlFieldData, m_fid_nodeValue);

			data = new CVRMLNodeData(value);
		}
		break;

	case BOOLEAN_ARRAY_DATA:
		{
			jbooleanArray values = (jbooleanArray)(env->GetObjectField(vrmlFieldData, m_fid_booleanArrayValue));
			if (values)	{
				jint len = env->GetArrayLength(values);
				jboolean isCopy;
				jboolean *pValues = env->GetBooleanArrayElements(values, &isCopy);

				if (pValues) {
					CVRMLBooleanArrayData *tmpData = new CVRMLBooleanArrayData();

					for (int i=0; i<len; i++) {
						tmpData->addValue((pValues[i] == JNI_TRUE) ? true : false);
					}

					data = (CVRMLFieldData *)tmpData;

					if (isCopy == JNI_TRUE)	{
						env->ReleaseBooleanArrayElements(values, pValues, 0);
					}
				}
			}
		}
		break;

	case INT_ARRAY_DATA:
		{
			jintArray values = (jintArray)(env->GetObjectField(vrmlFieldData, m_fid_intArrayValue));
			if (values)
			{
				jint len = env->GetArrayLength(values);
				jboolean isCopy;
				jint *pValues = env->GetIntArrayElements(values, &isCopy);

				if (pValues) {
					CVRMLIntArrayData *tmpData = new CVRMLIntArrayData();

					for (int i=0; i<len; i++) {
						tmpData->addValue(pValues[i]);
					}
					data = (CVRMLFieldData *)tmpData;

					if (isCopy == JNI_TRUE)	{
						env->ReleaseIntArrayElements(values, pValues, 0);
					}
				}
			}
		}
		break;

	case LONG_ARRAY_DATA:
		{
			jlongArray values = (jlongArray)(env->GetObjectField(vrmlFieldData, m_fid_longArrayValue));
			if (values)	{
				jint len = env->GetArrayLength(values);
				jboolean isCopy;
				jlong *pValues = env->GetLongArrayElements(values, &isCopy);

				if (pValues) {
					CVRMLLongArrayData *tmpData = new CVRMLLongArrayData();

					for (int i=0; i<len; i++) {
						tmpData->addValue(pValues[i]);
					}

					data = (CVRMLFieldData *)tmpData;

					if (isCopy == JNI_TRUE) {
						env->ReleaseLongArrayElements(values, pValues, 0);
					}
				}
			}
		}
		break;

	case FLOAT_ARRAY_DATA:
		{
			jfloatArray values = (jfloatArray)(env->GetObjectField(vrmlFieldData, m_fid_floatArrayValue));
			if (values) {
				jint len = env->GetArrayLength(values);
				jboolean isCopy;
				jfloat *pValues = env->GetFloatArrayElements(values, &isCopy);

				if (pValues) {
					CVRMLFloatArrayData *tmpData = new CVRMLFloatArrayData();

					for (int i=0; i<len; i++) {
						tmpData->addValue(pValues[i]);
					}

					data = (CVRMLFieldData *)tmpData;

					if (isCopy == JNI_TRUE) {
						env->ReleaseFloatArrayElements(values, pValues, 0);
					}
				}
			}
		}
		break;

	case DOUBLE_ARRAY_DATA:
		{
			jdoubleArray values = (jdoubleArray)(env->GetObjectField(vrmlFieldData, m_fid_doubleArrayValue));
			if (values) {
				jint len = env->GetArrayLength(values);
				jboolean isCopy;
				jdouble *pValues = env->GetDoubleArrayElements(values, &isCopy);

				if (pValues) {
					CVRMLDoubleArrayData *tmpData = new CVRMLDoubleArrayData();

					for (int i=0; i<len; i++) {
						tmpData->addValue(pValues[i]);
					}

					data = (CVRMLFieldData *)tmpData;

					if (isCopy == JNI_TRUE)	{
						env->ReleaseDoubleArrayElements(values, pValues, 0);
					}
				}
			}
		}
		break;

	case STRING_ARRAY_DATA:
		{
			jobjectArray values = (jobjectArray)(env->GetObjectField(vrmlFieldData, m_fid_stringArrayValue));
			if (values)	{
				CVRMLStringArrayData *tmpData = new CVRMLStringArrayData();

				jint len = env->GetArrayLength(values);
				for (int i=0; i<len; i++) {
					jstring jstr = (jstring)(env->GetObjectArrayElement(values, i));
					jboolean isCopy;
					const char *utf8Chars = env->GetStringUTFChars(jstr, &isCopy);
					tmpData->addValue(utf8Chars);

					if (isCopy == JNI_TRUE)	{
						env->ReleaseStringUTFChars(jstr, utf8Chars);
					}
					env->DeleteLocalRef(jstr);
				}

				data = (CVRMLFieldData *)tmpData;
			}
		}
		break;

	case NODE_ARRAY_DATA:
		{
			jobjectArray values = (jobjectArray)(env->GetObjectField(vrmlFieldData, m_fid_nodeArrayValue));
			if (values)	{
				CVRMLNodeArrayData *tmpData = new CVRMLNodeArrayData();

				jint len = env->GetArrayLength(values);
				for (int i=0; i<len; i++) {
					jobject vrmlNode = env->GetObjectArrayElement(values, i);
					if (vrmlNode) {
						tmpData->addValue(vrmlNode);
					}
					env->DeleteLocalRef(vrmlNode);
				}

				data = (CVRMLFieldData *)tmpData;
			}
		}
		break;

	default:
		break;
	}

	return data;
}
// vrmlNodeからPointLightオブジェクトを作る
CX3DPointLightNode::CX3DPointLightNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);
	
	// テンポラリノード(フィールド探査用)
	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "PointLight")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "ambientIntensity") == 0)
						{
							m_ambientIntensity.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "color") == 0)
						{
							m_color.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "intensity") == 0)
						{
							m_intensity.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "location") == 0)
						{
							m_location.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "radius") == 0)
						{
							m_radius.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "attenuation") == 0)
						{
							m_attenuation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "on") == 0)
						{
							m_on.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "global") == 0)
						{
							m_global.setValue(data);
						}

						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}
CX3DTextureTransformNode::CX3DTextureTransformNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);
	
	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "TextureTransform")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "center") == 0)
						{
							m_center.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "rotation") == 0)
						{
							m_rotation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "scale") == 0)
						{
							m_scale.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "translation") == 0)
						{
							m_translation.setValue(data);
						}

						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}
CX3DViewpointNode::CX3DViewpointNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);
	
	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "Viewpoint")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "fieldOfView") == 0)
						{
							m_fieldOfView.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "jump") == 0)
						{
							m_jump.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "retainUserOffsets") == 0)
						{
							m_retainUserOffsets.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "orientation") == 0)
						{
							m_orientation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "position") == 0)
						{
							m_position.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "centerOfRotation") == 0)
						{
							m_centerOfRotation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "description") == 0)
						{
							m_description.setValue(data);
						}

						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}
CX3DOpenHRPHumanoidNode::CX3DOpenHRPHumanoidNode(jobject vrmlNode)
{
	if (!vrmlNode)
	{
		m_vrmlNode = NULL;
		return;
	}

	CJNIUtil *ju = CJNIUtil::getUtil();

	if (!ju->isInstanceOfVRMLNode(vrmlNode))
	{
		fprintf(stderr, "vrmlNode is not instance of VRMLNode [%s:%d]\n", __FILE__, __LINE__);
		exit(1);
	}

	m_vrmlNode = ju->env()->NewGlobalRef(vrmlNode);

	CX3DNode *tmpNode = new CX3DNode(vrmlNode);
	if (tmpNode)
	{
		char *nodeName = tmpNode->getNodeName();

		if (nodeName && strcmp(nodeName, "Humanoid")==0)
		{
			int n = tmpNode->countFields();
			for (int i=0; i<n; i++)
			{
				char *pFieldName = tmpNode->getFieldName(i);
				if (pFieldName)
				{
					std::string fieldName = pFieldName;

					CVRMLFieldData *data = tmpNode->createFieldValue((char *)(fieldName.c_str()));
					if (data)
					{
						if (strcmp(fieldName.c_str(), "center") == 0)
						{
							m_center.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "rotation") == 0)
						{
							m_rotation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "scale") == 0)
						{
							m_scale.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "scaleOrientation") == 0)
						{
							m_scaleOrientation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "translation") == 0)
						{
							m_translation.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "name") == 0)
						{
							m_name.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "info") == 0)
						{
							m_info.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "joints") == 0)
						{
							m_joints.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "segments") == 0)
						{
							m_segments.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "sites") == 0)
						{
							m_sites.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "version") == 0)
						{
							m_version.setValue(data);
						}
						else if (strcmp(fieldName.c_str(), "viewpoints") == 0)
						{
							m_viewpoints.setValue(data);
						}

						else if (strcmp(fieldName.c_str(), "humanoidBody") == 0)
						{
							m_humanoidBody.setValue(data);
						}
						delete data;
					}
				}
			}
		}
		delete tmpNode;
	}
}