/** 
* @addtogroup			workflow
* @{
*/

/**
* @file					jy_create_material_code.cpp
*
* @brief				create material code according to some rev master properties
* 
* @author				James Pang
*
* @history				
* ===================================================================================
* Date					Name				Description
* 27-Jul-2009			James				created
* 03-Nov-2009			James				modify EPM_reference_attachment to EPM_target_attachment
* 17-Nov-2009			James				add check for JyErpNoSyncApp
*						lwh					lwh add -pre,-fixed_prop parameter 
*/

/**
* @remarks:			handler usage description
*
* @Handler:			jy-create-material-code 
*
* @Description:		This handler will assign some value to its form property
*
* @Syntax:			jy-create-material-code -type=产品,零组件 -required_props=prop1,prop2,prop3 -sid_leng=3 -target_prop=target_prop_name [-debug=true|false]
* @Arguments:		-type = ItemRevision types, like 产品,零组件
*								specified target ItemRevision will be processed, others skipped, 
*								eg: 产品,零组件
*
*					-required_props = prop1,prop2,prop3,...
*								specified properties will be changed
*
*					-sid_leng = 3
*								material code sequence number's length
*
*					-target_prop = target property
*								the new prop value assigned to this property
*					
*					-debug = true | false
*								When the argument is set to 'true' (case-insensitive), there will be more messages written in the syslog file. The default value is false.
*					-pre = 4 
*							截取合成后属性的前几位
*
*					-fixed_prop = fixed property
*								截取后的属性名
*					
* @Placement:       not specified
* 
* @Restrictions:	none
*
*/

#pragma warning (disable: 4996) 
#pragma warning (disable: 4819) 

/**
* @headerfile			tcua 头文件
*/

#include <property/propdesc.h>
#include <epm/epm.h>
#include <tccore/item.h>
#include <tccore/grmtype.h>
#include <tccore/grm.h>
#include <sa/role.h>
#include <tccore/imantype.hxx>
#include <sa/am.h>
#include <tccore/aom.h>
#include <tccore/aom_prop.h>
#include <property/prop_errors.h>
#include <lov/lov_errors.h>
#include <lov/lov.h>
#include <tccore/tctype.h>
#include <form/formtype.h>

#include <res/res_itk.h>
#include <epm/signoff.h>
/**
* @headerfile			standard c & cpp header files
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <math.h>

#include <string>
#include <vector>
#include <map>
#include <fstream>
//#include <iostream>
using namespace std;

/**
* @headerfile			user's header files
*/
#include "register_handler_methods.h"
#include "error_handling.h"
#include "string_helper.h"
#include "itk_service_common.h"

//static int CycleLovFilter( tag_t lov_tag, const char *prop_value, int lov_order, int filter_level, string &prop_desc )
//{
//	int ifail = ITK_ok;
//printf("CycleLovFilter\n");
//	if (lov_tag == NULLTAG)
//		return ITK_ok;
//	else if ( prop_desc.size()==0 )
//	{
//printf("filter_level=%d,lov_order=%d\n",filter_level,lov_order);
//		if (filter_level == lov_order)
//		{
//			int n_values = 0, lov_index = 0;
//			char **lov_values = NULL;
//			int	*lov_int=0;
//			logical find_prop_value = FALSE;
//
//			ITKCALL( LOV_ask_values_string( lov_tag, &n_values, &lov_values ) );
//
//			for (int li=0; li<n_values; li++)
//			{
//				printf("lov_values[li]=%s\n",lov_values[li]);
//				if (strcmp(lov_values[li], prop_value) == 0)
//				{
//					lov_index = li;
//					find_prop_value = TRUE;
//					break;
//				}
//			}
//			MEM_free(lov_values);
//
//
//			if (find_prop_value)
//			{
//				LOV_usage_t usage;
//				char        **desc_strings = NULL;
//				logical     *is_null = NULL;
//				logical     *is_empty = NULL;
//				tag_t	*values_tag = NULL;
//				printf("开始取描述值\n");
//				//ITKCALL( LOV_ask_lov_tag (lov_tag,&usage,&n_values,&values_tag,&is_null, &is_empty ) );
//				//ITKCALL( LOV_ask_values_tag (lov_tag,&n_values,&values_tag) );
//				//ITKCALL (LOV_is_value_valid_string (lov_tag,
//				ITKCALL( LOV_ask_value_descriptions( lov_tag, &usage,
//					&n_values, &desc_strings, &is_null, &is_empty ) );
//				if (is_null[lov_index]==FALSE && is_empty[lov_index]==FALSE)
//				{
//					printf("find_prop_value desc_strings[lov_index]=%s\n",desc_strings[lov_index]);
//					prop_desc.assign(desc_strings[lov_index]);
//					printf("prop_desc=%s\n",prop_desc.c_str());
//				}
//				MEM_free(desc_strings);
//				MEM_free(is_null);
//				MEM_free(is_empty);
//
//				return ITK_ok;
//			}
//		}		
//		else
//		{
//			printf("n_listOfFilters\n");
//			int n_listOfFilters = 0, *listOfFiltersIndexes = NULL;
//			tag_t *listOfFilters = NULL;
//
//			ITKCALL( LOV_ask_value_filters( lov_tag, &n_listOfFilters, &listOfFiltersIndexes, &listOfFilters ) );
//			if (n_listOfFilters>0)
//			{
//				for (int li=0; li<n_listOfFilters; li++)
//				{
//					if (prop_desc.size()==0)
//					{
//						int new_filter_level = filter_level + 1;
//						//if( listOfFilters[li]!=NULLTAG)
//							ifail = CycleLovFilter( listOfFilters[li], prop_value, lov_order, new_filter_level, prop_desc );
//					}		
//					else
//						break;
//				}
//				MEM_free( listOfFiltersIndexes );
//				MEM_free( listOfFilters );
//			}
//		}	
//	}
//
//	return ifail;
//}
//
//static int CycleLovFilter( tag_t lov_tag, const char *prop_value, int lov_order, int filter_level, string &prop_desc )
//{
//	int ifail = ITK_ok;
//
//	if (lov_tag == NULLTAG)
//		return ITK_ok;
//	else if ( prop_desc.size()==0 )
//	{
//		if (filter_level == lov_order)
//		{
//			int n_values = 0, lov_index = 0;
//			char **lov_values = NULL;
//			logical find_prop_value = FALSE;
//
//			ITKCALL( LOV_ask_values_string( lov_tag, &n_values, &lov_values ) );
//			for (int li=0; li<n_values; li++)
//			{
//				if (strcmp(lov_values[li], prop_value) == 0)
//				{
//					lov_index = li;
//					find_prop_value = TRUE;
//					break;
//				}
//			}
//			MEM_free(lov_values);
//
//			if (find_prop_value)
//			{
//				LOV_usage_t usage;
//				char        **desc_strings = NULL;
//				logical     *is_null = NULL;
//				logical     *is_empty = NULL;
//
//				ITKCALL( LOV_ask_value_descriptions( lov_tag, &usage,
//					&n_values, &desc_strings, &is_null, &is_empty ) );
//				if (is_null[lov_index]==FALSE && is_empty[lov_index]==FALSE)
//				{
//					prop_desc.assign(desc_strings[lov_index]);
//				}
//				MEM_free(desc_strings);
//				MEM_free(is_null);
//				MEM_free(is_empty);
//
//				return ITK_ok;
//			}
//		}		
//		else
//		{
//			int n_listOfFilters = 0, *listOfFiltersIndexes = NULL;
//			tag_t *listOfFilters = NULL;
//
//			ITKCALL( LOV_ask_value_filters( lov_tag, &n_listOfFilters, &listOfFiltersIndexes, &listOfFilters ) );
//			if (n_listOfFilters>0)
//			{
//				for (int li=0; li<n_listOfFilters; li++)
//				{
//					if (prop_desc.size()==0)
//					{
//						int new_filter_level = filter_level + 1;
//						ifail = CycleLovFilter( listOfFilters[li], prop_value, lov_order, new_filter_level, prop_desc );
//					}		
//					else
//						break;
//				}
//				MEM_free( listOfFiltersIndexes );
//				MEM_free( listOfFilters );
//			}
//		}	
//	}
//
//	return ifail;
//}
//static int FindPropLovDesc( tag_t object, const char *prop_name, PROP_value_type_t prop_type, string &prop_value )
//{
//	if (object==NULLTAG)
//		return POM_inst_not_loaded;
//
//	prop_value.clear();
//	printf("prop_value.clear\n");
//	//数组属性统一处理
//	int max_prop_elems = 0;
//	ITKCALL( AOM_ask_max_num_elements( object, prop_name, &max_prop_elems ) );
//	if( max_prop_elems != 1 )
//	{
//		printf("max_prop_elems!=1\n");
//		char *d_vlaue = NULL;
//		ITKCALL( AOM_UIF_ask_value( object, prop_name, &d_vlaue ) );
//		if (d_vlaue && *d_vlaue)
//		{
//			prop_value.assign(d_vlaue);
//			MEM_free(d_vlaue);
//			return ITK_ok;
//		}
//	}
//	else
//	{
//		printf("else\n");
//		if (prop_type == PROP_string)
//		{
//			tag_t prop_descriptor = NULLTAG;
//			ITKCALL( AOM_ask_descriptor( object, prop_name, &prop_descriptor ) );
//
//			logical is_lov_des_attached = FALSE;
//			ITKCALL( PROPDESC_is_lov_desc_attach( prop_descriptor, &is_lov_des_attached ) );
//			printf("is_lov_des_attached\n");
//			if (is_lov_des_attached) //如果当前属性已经是lov的描述，则不再处理，仅赋值给返回对象
//			{
//				char *str_value = NULL;
//				printf("当前属性已经是lov的描述\n");
//				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );
//				if (str_value && *str_value)
//				{
//					prop_value.assign(str_value);
//					MEM_free(str_value);
//				}
//			}
//			else
//			{
//				char *str_value = NULL;
//				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );
//
//				if (str_value && *str_value) //仅在属性有值的情况下取其lov描述
//				{
//					tag_t lov_tag = NULLTAG;
//					ITKCALL( AOM_ask_lov( object, prop_name, &lov_tag ) );
//					if (lov_tag) //如果没有与属性关联的lov，则不处理
//					{
//						int lov_order = 0;
//
//						char object_type[WSO_name_size_c + 1] = "";
//						ITKCALL( WSOM_ask_object_type2( object, object_type ) );
//						ITKCALL( LOV_ask_attached_dependency_order( object_type, prop_name, &lov_order ) );
//
//						string prop_desc;
//						CycleLovFilter(lov_tag, str_value, lov_order, 1, prop_desc );
//						if (prop_desc.size()>0)
//							prop_value.assign(prop_desc);
//					}
//					//if (lov_tag) //如果没有与属性关联的lov，则不处理
//					//{
//					//	int lov_order = 0;
//
//					//	char object_type[WSO_name_size_c + 1] = "";
//					//	ITKCALL( WSOM_ask_object_type2( object, object_type ) );
//					//	ITKCALL( LOV_ask_attached_dependency_order( object_type, prop_name, &lov_order ) );
//					//	string prop_desc;
//					//	if(lov_order==0)
//					//	{
//					//		int n_values = 0, lov_index = 0;
//					//		char **lov_values = NULL;
//					//		logical find_prop_value = FALSE;
//					//		LOV_usage_t usage;
//					//		char        **desc_strings = NULL;
//					//		logical     *is_null = NULL;
//					//		logical     *is_empty = NULL;
//					//		printf("开始取描述值\n");
//					//		ITKCALL( LOV_ask_value_descriptions( lov_tag, &usage,
//					//			&n_values, &desc_strings, &is_null, &is_empty ) );
//					//		if (is_null[lov_index]==FALSE && is_empty[lov_index]==FALSE)
//					//		{
//					//			printf("desc_strings[lov_index]=%s\n",desc_strings[lov_index]);
//					//			prop_desc.assign(desc_strings[lov_index]);
//					//		}
//					//		MEM_free(desc_strings);
//					//		MEM_free(is_null);
//					//		MEM_free(is_empty);						
//					//	}
//					//	else
//					//	{
//					//	//string prop_desc;
//					//	CycleLovFilter(lov_tag, str_value, lov_order, 1, prop_desc );
//
//					//	}
//					//	if (prop_desc.size()>0)
//					//		prop_value.assign(prop_desc);
//					//}
//
//					if (prop_value.size()==0)
//					{
//						prop_value.assign(str_value);
//					}
//
//					MEM_free(str_value);
//					return ITK_ok;
//				}
//			}
//		}
//		else if (prop_type == PROP_int)
//		{
//			int int_value = NULL;
//			ITKCALL( AOM_ask_value_int( object, prop_name, &int_value ) );
//			char buf[100] = "";
//			sprintf( buf, "%d", int_value );
//			prop_value.assign(buf);
//		}
//	}
//
//	return ITK_ok;
//}

int IncludeChinese(char *str)//返回0：无中文，返回1：有中文
{
   char c;
   int n=0;
   while(1)
   {
       c=*str++;
       if (c==0) break;  //如果到字符串尾则说明该字符串没有中文字符
       if (c&0x80)        //如果字符高位为1且下一字符高位也是1则有中文字符
	   {
            if (*str & 0x80) 
			{	
			n++;			
			};

	   }
   }
   return n;
} 

static int CycleLovFilter(map<int,string> &lov_rel_props_value, const char *prop_name, 
						   tag_t lov_tag,  int lov_order, int filter_level, const char *prop_value, string &prop_desc)
{
	int ifail = ITK_ok;

	if (lov_tag == NULLTAG)
		return ITK_ok;
	printf("prop_name = %s, prop_vlaue = %s, prop_desc = %s\n", prop_name, prop_value, prop_desc.c_str());	
	printf("prop_desc.size() = %d, filter_level = %d, lov_order = %d\n", prop_desc.size(), filter_level, lov_order);

	if (prop_desc.size() == 0)
	{
		if (filter_level == lov_order)
		{
			int n_values = 0, lov_index = 0;
			char **lov_values = NULL;
			logical find_prop_value = FALSE;

			ITKCALL( LOV_ask_values_string( lov_tag, &n_values, &lov_values ) );
			for (int li=0; li<n_values; li++)
			{
				if (strcmp(lov_values[li], prop_value) == 0)
				{
					lov_index = li;
					find_prop_value = TRUE;
					break;
				}
			}
			MEM_free(lov_values);

			if (find_prop_value)
			{
				LOV_usage_t usage;
				char        **desc_strings = NULL;
				logical     *is_null = NULL;
				logical     *is_empty = NULL;

				ITKCALL( LOV_ask_value_descriptions( lov_tag, &usage,
					&n_values, &desc_strings, &is_null, &is_empty ) );

				if (is_null[lov_index]==FALSE && is_empty[lov_index]==FALSE)
				{	
					prop_desc.assign(desc_strings[lov_index]);
				}
				MEM_free(desc_strings);
				MEM_free(is_null);
				MEM_free(is_empty);

				return ITK_ok;
			}
		}
		else
		{
			int current_level_value_index = 0;
			map<int,string>::iterator current_order_value = lov_rel_props_value.find(filter_level);
	
			//找到跟filter_level对应的属性值的索引
			if (current_order_value != lov_rel_props_value.end())
			{
				logical find_secondary_level_index = 0;

				int n_values = 0;
				char **lov_values = NULL;
				logical find_prop_value = FALSE;

				ITKCALL( LOV_ask_values_string( lov_tag, &n_values, &lov_values ) );
				for (int li=0; li<n_values; li++)
				{
					if (strcmp(lov_values[li], current_order_value->second.c_str()) == 0)
					{
						current_level_value_index = li;
						break;
					}
				}
				MEM_free(lov_values);

				//找到根filter_level索引值对应的子lov对象
				int n_listOfFilters = 0, *listOfFiltersIndexes = NULL;
				tag_t *listOfFilters = NULL;
				ITKCALL( LOV_ask_value_filters( lov_tag, &n_listOfFilters, &listOfFiltersIndexes, &listOfFilters ) );
				map<int,tag_t> filtersMap;
				map<int,tag_t>::iterator filtersMapIter;
				for (int li=0; li<n_listOfFilters; li++)
				{
					filtersMap.insert(make_pair(listOfFiltersIndexes[li], listOfFilters[li]));
				}
				MEM_free(listOfFilters);
				MEM_free(listOfFiltersIndexes);

				if ((filtersMapIter = filtersMap.find(current_level_value_index)) != filtersMap.end())
				{
					ifail = CycleLovFilter(lov_rel_props_value, prop_name, filtersMapIter->second, lov_order, filter_level+1, prop_value, prop_desc);
				}				
			}	
		}
	}

	return ifail;
}

static int FindPropLovDesc( tag_t object, const char *prop_name, PROP_value_type_t prop_type, string &prop_value )
{
	int ifail = ITK_ok;
	char buf[BUFSIZ] = "";

	if (object==NULLTAG)
		return POM_inst_not_loaded;

	prop_value.clear();

	//数组属性统一处理
	int max_prop_elems = 0;
	ITKCALL( AOM_ask_max_num_elements( object, prop_name, &max_prop_elems ) );
	if( max_prop_elems != 1 )
	{
		char *d_vlaue = NULL;
		ITKCALL( AOM_UIF_ask_value( object, prop_name, &d_vlaue ) );
		if (d_vlaue && *d_vlaue)
		{
			prop_value.assign(d_vlaue);
			MEM_free(d_vlaue);
			return ITK_ok;
		}
	}
	else
	{
		if (prop_type == PROP_string)
		{
			tag_t prop_descriptor = NULLTAG;
			ITKCALL( AOM_ask_descriptor( object, prop_name, &prop_descriptor ) );

			logical is_lov_des_attached = FALSE;
			ITKCALL( PROPDESC_is_lov_desc_attach( prop_descriptor, &is_lov_des_attached ) );
			if (is_lov_des_attached) //如果当前属性已经是lov的描述，则不再处理，仅赋值给返回对象
			{
				char *str_value = NULL;
				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );
				if (str_value && *str_value)
				{
					prop_value.assign(str_value);
					MEM_free(str_value);
				}
			}
			else
			{
				char *str_value = NULL;
				ITKCALL( AOM_ask_value_string( object, prop_name, &str_value ) );

				if (str_value && *str_value) //仅在属性有值的情况下取其lov描述
				{
					tag_t lov_tag = NULLTAG;
					ITKCALL( AOM_ask_lov( object, prop_name, &lov_tag ) );

					if (lov_tag) //如果没有与属性关联的lov，则不处理
					{	
						map<int,string> lov_rel_props;

						char* object_type = NULL;
						ITKCALL( WSOM_ask_object_type2( object, &object_type ) );

						//得到Form的存储类
						//tag_t class_id = NULLTAG;
						//ITKCALL( POM_class_of_instance( object, &class_id ) );
						//char *class_name = NULL;
						//ITKCALL( POM_name_of_class( class_id, &class_name ) );
						//if (strcmp(class_name, "Form") == 0)
						//{
						//	tag_t type_tag = NULLTAG;
						//	ITKCALL( TCTYPE_find_type( object_type, NULL, &type_tag ) );

						//	char *def_class_name = NULL;
						//	ITKCALL( FORMTYPE_ask_def_class_name( type_tag, &def_class_name ) );
						//	strcpy( object_type, def_class_name );
						//	MEM_free(def_class_name);
						//}
						//MEM_free(class_name);
						
						//得到跟当前Form及LOV关联的所有属性
						int n_attach = 0, *orders = NULL, *n_parents = NULL;
						char **type_names = NULL, **prop_names = NULL;
						logical *descAttaches = NULL;
						ITKCALL( LOV_ask_attached_properties_info( lov_tag, &n_attach, &type_names, &prop_names, &orders, &n_parents, &descAttaches ) );
						for (int ai=0; ai<n_attach; ai++)
						{
							if (strcmp(type_names[ai], object_type) == 0)
							{
								printf("orders[ai] = %d\n", orders[ai]);
								lov_rel_props.insert(make_pair(orders[ai], prop_names[ai]));
							}
						}
						MEM_free(orders);
						MEM_free(n_parents);
						MEM_free(descAttaches);
						MEM_free(type_names);
						MEM_free(prop_names);

						map<int,string> lov_rel_props_value;
						for (map<int,string>::iterator iter = lov_rel_props.begin(); iter != lov_rel_props.end(); iter++)
						{
							char *prop_value = NULL;
							ITKCALL( AOM_ask_value_string(object, iter->second.c_str(), &prop_value) );
							lov_rel_props_value.insert(make_pair(iter->first, prop_value));
							MEM_free(prop_value);
						}

						int lov_order = 0;
						ITKCALL( LOV_ask_attached_dependency_order( object_type, prop_name, &lov_order ) );
printf("lov_order = %d\n", lov_order);
						string prop_desc;
						CycleLovFilter( lov_rel_props_value, prop_name, lov_tag, lov_order, 1, str_value, prop_desc);
						if (prop_desc.size()>0)
							prop_value.assign(prop_desc);				
					}

					if (prop_value.size()==0)
					{
						prop_value.assign(str_value);
					}

					MEM_free(str_value);
					return ITK_ok;
				}
			}
		}
		else if (prop_type == PROP_int)
		{
			int int_value = NULL;
			ITKCALL( AOM_ask_value_int( object, prop_name, &int_value ) );
			char buf[100] = "";
			sprintf( buf, "%d", int_value );
			prop_value.assign(buf);
		}
	}

	return ITK_ok;
}


int jy_create_material_code(EPM_action_message_t msg)
{
	int ifail = ITK_ok;
	logical is_debug = FALSE;
	char fixed_prop[WSO_name_size_c + 1]="";
	char buf[BUFSIZ] = "", *flag = NULL, *value = NULL;
	
	//item master form relation type
	tag_t master_form_rel_type = NULLTAG;
	ITKCALL( GRM_find_relation_type( TC_master_form_rtype, &master_form_rel_type ) );

	//parse some arguments
	map<string,string> item_types_map;
	map<string,string>::iterator item_types_map_iter = item_types_map.begin();
	vector<string>     required_props_vec;
	int sid_leng = 0, max_sid = 0, pre_len = 0;
	
	char target_prop[WSO_name_size_c + 1] = "";
	int num_of_arguments = TC_number_of_arguments( msg.arguments );
	for (int i=0; i<num_of_arguments; i++)
	{
		ITKCALL( ITK_ask_argument_named_value( TC_next_argument( msg.arguments ), &flag, &value ) );
printf( "value = %s\n", value );
		if ( strcmp( flag, "type" ) == 0 && value != NULL )
		{
			vector<string> ans;
			Split( value, ',', ans );
			for (size_t j=0; j<ans.size(); j++)
			{
				item_types_map.insert(make_pair(ans[j],ans[j]));		
			}
		}
		else if ( strcmp( flag, "required_props" ) == 0 && value != NULL )
		{
			vector<string> ans;
			Split( value, ',', ans ); printf( "ans size = %d\n", ans.size() );
			for (size_t j=0; j<ans.size(); j++)
			{
				required_props_vec.push_back(ans[j]);		
			}
		}
		else if ( strcmp( flag, "sid_leng" ) == 0 && value != NULL )
		{
			sid_leng = atoi(value); 
			max_sid = (int)(pow( 10.0, sid_leng )) - 1;
		}
		else if ( strcmp( flag, "target_prop" ) == 0 && value != NULL )
		{
			strcpy( target_prop, value );
		} //check debug indicator
		else if( strcmp( flag, "debug" ) == 0 && value != NULL )
		{
			if( strcmp( value, "true" ) == 0 )
				is_debug = TRUE;
		}
		else if( strcmp( flag, "pre" ) == 0 && value != NULL )
		{
			//if( strcmp( value, "true" ) == 0 )
			//	is_debug = TRUE;
			pre_len = atoi(value);
		}
		else if( strcmp( flag, "fixed_prop" ) == 0 && value != NULL )
		{
			//if( strcmp( value, "true" ) == 0 )
			//	is_debug = TRUE;
			strcpy( fixed_prop, value );
		}
		MEM_free( flag );
		MEM_free( value );
	}

//STEP 1:
	//check handler arguments
	if (item_types_map.size()==0)
	{
		printf( ("type argument is not specified, please check!\n") );
		return EPM_missing_req_arg;
	}
	else if ( required_props_vec.size()==0)
	{
		printf( ("required_props argument is not specified, please check!\n") );
		return EPM_missing_req_arg;
	}
	else if ( sid_leng==0 )
	{
		printf( ("sid_leng argument is not valid, please check!\n") );
		return EPM_missing_req_arg;
	}
	else if (strlen(target_prop)==0 )
	{
		printf( ("target_prop argument is not valid, please check!\n") );
		return EPM_missing_req_arg;
	}
	else if (pre_len==0 )
	{
		printf( ("pre argument is not valid, please check!\n") );
		return EPM_missing_req_arg;
	}
	else if (strlen(fixed_prop)==0 )
	{
		printf( ("fixed_prop argument is not valid, please check!\n") );
		return EPM_missing_req_arg;
	}
	logical prop_not_defined = FALSE;
	logical lov_has_no_value = FALSE;
	item_types_map_iter = item_types_map.begin();
	for (; item_types_map_iter!=item_types_map.end(); item_types_map_iter++)
	{
		tag_t item_type = NULLTAG, 
			parent_type_tag = NULLTAG;
		char* item_type_class = NULL,
			*parent_type_class = NULL;
		ITKCALL( TCTYPE_find_type( item_types_map_iter->first.c_str(), NULL, &item_type ) );
		ITKCALL( TCTYPE_ask_class_name2( item_type, &item_type_class ) );
		printf("\nitem_type_class=%s\n",item_type_class);
		ITKCALL( TCTYPE_ask_parent_type( item_type,&parent_type_tag) );
		ITKCALL( TCTYPE_ask_class_name2( parent_type_tag, &parent_type_class ) );
		//TC8==============================
		//if (strcmp( parent_type_class, "Item" ) != 0)
		//if (strcmp( item_type_class, "Item" ) != 0)
		if	(strstr(item_type_class,"XY")==NULL)
		{
			//sprintf( buf, "type %s not Item or its sub type%s\n", item_types_map_iter->first.c_str() );
			sprintf( buf, "%s is not XY Item or its sub type%s\n", item_types_map_iter->first.c_str() );
			printf( (buf) );
			break;
		}

		char *rev_master_type_name = NULL;
		ITKCALL( ITEM_ask_rev_master_form_type( item_types_map_iter->first.c_str(), &rev_master_type_name ) );

		tag_t rev_master_type = NULLTAG;
		ITKCALL( TCTYPE_find_type( rev_master_type_name, NULL, &rev_master_type ) );

		for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		{
			char one_prop[WSO_name_size_c + 1] = "";
			strcpy( one_prop, required_props_vec[ri].c_str() );

			tag_t pd_tag = NULLTAG;
			ifail = TCTYPE_ask_property_by_name( rev_master_type, one_prop, &pd_tag );
			if (ifail != ITK_ok || pd_tag == NULLTAG)
			{
				sprintf( buf, "property %s not found from type %s\n", one_prop, rev_master_type_name );
				printf( (buf) );

				prop_not_defined = TRUE;
				break;
			}
		}

		if (!prop_not_defined)
		{
			tag_t pd_tag = NULLTAG;
			ifail = TCTYPE_ask_property_by_name( rev_master_type, target_prop, &pd_tag );
			if (ifail != ITK_ok || pd_tag == NULLTAG)
			{
				sprintf( buf, "property %s not found from type %s\n", target_prop, rev_master_type_name );
				printf( (buf) );

				prop_not_defined = TRUE;
				break;
			}
		}

		if (prop_not_defined)
		{
			break;
		}
	}

	if (prop_not_defined)
	{
		return PROP_no_properties;
	}

	if ( is_debug ) //print arguments specified for handler
	{
		item_types_map_iter = item_types_map.begin();
		for (; item_types_map_iter!=item_types_map.end(); item_types_map_iter++)
		{
			sprintf( buf, "Type: %s, ", item_types_map_iter->first.c_str() );
			printf( (buf) );
		}
		sprintf( buf, "\n" );
		printf( (buf) );

		for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		{
			sprintf( buf, "Prop: %s, ", required_props_vec[ri].c_str() );
			printf( (buf) );
		}
		sprintf( buf, "Prop: %s\n", target_prop );
		printf( (buf) );

		sprintf( buf, "Max Flow ID Leng: %d\n", max_sid );
		printf( (buf) );
	}

//STEP 2:
	//retrieve item revisions related in reference's list
	tag_t job = NULLTAG, root_task = NULLTAG;
	ITKCALL( EPM_ask_job( msg.task, &job ) );
	ITKCALL( EPM_ask_root_task( job, &root_task ) );

	//current task's reference list
	int reference_count = 0;
	tag_t *reference_list = NULL;
	ITKCALL( EPM_ask_attachments( root_task, EPM_target_attachment, &reference_count, &reference_list ) );
	vector<tag_t> reference_revs_vec;
	for (int ri=0; ri<reference_count; ri++)
	{
		tag_t class_id = NULLTAG;
		ITKCALL( POM_class_of_instance( reference_list[ri], &class_id ) );
		if ( class_id != NULLTAG )
		{
			char *class_name = NULL;
			ITKCALL( POM_name_of_class( class_id, &class_name ) );
			printf("\nclass_name=%s\n",class_name);
			//TC8=======================
			//if ( class_name && *class_name && strcmp( class_name, "ItemRevision" ) == 0 )
			//if ( class_name && *class_name && strstr( class_name, "Revision" ) != 0 )
			if ( class_name && *class_name && strstr( class_name, "XY" ) != NULL && strstr( class_name, "Revision" ) != NULL )
			{
				tag_t item_tag = NULLTAG;
				ITKCALL( ITEM_ask_item_of_rev( reference_list[ri], &item_tag ) );

				char* item_type = NULL;
				ITKCALL( ITEM_ask_type2( item_tag, &item_type ) );

				if (item_types_map.find(item_type)!=item_types_map.end())
				{
					reference_revs_vec.push_back(reference_list[ri]);
				}
			}

			MEM_free(class_name);
		}
	}

	if (is_debug)
	{
		sprintf( buf, "Total %d objects will be processed\n", reference_revs_vec.size() );
		printf( (buf) );
	}

	//处理所有的版本
	printf( "111111111\n" );
	for (int vi=0; vi<(int)reference_revs_vec.size(); vi++)
	{
		tag_t one_rev = reference_revs_vec[vi];

		int form_count = 0;
		tag_t *form_list = NULL, master_form = NULLTAG;
		ITKCALL( GRM_list_secondary_objects_only( one_rev, master_form_rel_type, &form_count, &form_list ) );
		master_form = form_list[0];
		MEM_free(form_list);

		//检查target_prop是否有值
		//logical is_null_empty = FALSE;
		//ITKCALL( AOM_is_null_empty( master_form, target_prop, TRUE, &is_null_empty ) );
		//if (!is_null_empty)
		//{
		//	sprintf( "target prop %s had value already!\n", target_prop );
		//	printf( (buf) );
		//	continue;
		//}

		////检查JyErpNoSyncApp（EPR编码申请）是否为“申请”
		//char *apply_value = NULL;
		//ITKCALL( AOM_ask_value_string( master_form, "JyErpNoSyncApp", &apply_value ) );
		//if ( apply_value && *apply_value && strcmp( apply_value, "不申请" ) == 0 )
		//{
		//	MEM_free(apply_value);
		//	continue;
		//}
		//MEM_free(apply_value);

		char *apply_value = NULL;
		ITKCALL( AOM_ask_value_string( master_form, "ItemIsERP", &apply_value ) );
		if(stricmp(apply_value,"true") == 0)
		{
			MEM_free(apply_value);
			continue;
		}
		char *target_value = NULL;
		ITKCALL( AOM_ask_value_string( master_form, target_prop, &target_value ) );
		//如果有值则不写
		if(strcmp(target_value,"") != 0)
		{
			MEM_free(target_value);
			continue;
		}
		//if ( apply_value && *apply_value && strcmp( apply_value, "不申请" ) == 0 )
		//{
		//	MEM_free(apply_value);
		//	continue;
		//}
		MEM_free(apply_value);
		map<string,PROP_value_type_t> prop_type_map;
		map<string,PROP_value_type_t>::iterator prop_type_map_iter;
		//得到指定属性的值类型
		printf( "222222222\n" );
		for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		{
			printf( "required_props_vec[ri]=%s\n",required_props_vec[ri].c_str() );
			PROP_value_type_t valtype;
			char *valtype_n = NULL;
			ITKCALL( AOM_ask_value_type( master_form, required_props_vec[ri].c_str(), &valtype, &valtype_n ) );
			//if (is_debug)
			{
				sprintf( buf, "prop type = %s\n", valtype_n );
			}
			MEM_free(valtype_n);
			prop_type_map.insert( make_pair(required_props_vec[ri], valtype) );
		}
		printf( "3333333333\n" );
		//得到指定的属性
		string material_code_mark("");
		for ( int ri=0; ri<(int)required_props_vec.size(); ri++)
		{
			prop_type_map_iter = prop_type_map.find(required_props_vec[ri]);
			printf( "prop_type_map_iter\n" );
			PROP_value_type_t valtype = prop_type_map_iter->second;

			string prop_value;
			ITKCALL(RES_checkout2(master_form,"","","",RES_EXCLUSIVE_RESERVE));
			ITKCALL(RES_cancel_checkout (master_form,false));
			printf( "=============FindPropLovDesc\n" );
			FindPropLovDesc( master_form, required_props_vec[ri].c_str(), valtype, prop_value );
			printf( "FindPropLovDesc=============\n" );
			if (prop_value.size()>0)
			{
				material_code_mark.append(prop_value);
			}
		}
		printf( "material_code_mark=%s\n",material_code_mark.c_str() );
		if(material_code_mark.empty())
		{
			printf( ("编码未指定, please check!\n") );
			return EPM_task_not_complete;
		}
		char *newID = NULL;
		ITKCALL( SERVICE_internal_part_no( material_code_mark.c_str(), sid_leng, 1, max_sid, 1, &newID ) );
		if (newID && *newID && strlen(newID)>0)
		{
			printf("newID=%s\n",newID);
			//sprintf(newID,"%s测试","lala");
			if(IncludeChinese(newID)>0)
			{
				printf("物料编码:%s,含有中文,请联系系统管理员解决此问题!\n",newID);
				return EPM_task_not_complete;
			}
			
			material_code_mark.assign(newID);
			MEM_free(newID);
		}
		
		if (is_debug)
		{
			sprintf( buf, "new material code is %s\n", material_code_mark.c_str() );
			printf( (buf) );
		}

		//检查写权限
		logical can_change_form = FALSE;
		ITKCALL( AM_check_privilege(master_form, "WRITE", &can_change_form ) );
		PROP_protection_t  protection;
		tag_t	prop_tag=NULLTAG;
		ITKCALL(TCTYPE_ask_property_by_name(master_form, target_prop, &prop_tag));
		
		//=========================权限放开
		if (can_change_form)
		{
			//TC8==============
			ITKCALL(AOM_load (master_form) );
			ITKCALL(RES_checkout2(master_form,"","","",RES_EXCLUSIVE_RESERVE));
			ITKCALL(RES_cancel_checkout (master_form,false));
			//ITKCALL( AOM_unlock( master_form ) );
			//ITKCALL( AOM_lock( master_form ) );
			 //logical  on_or_off=true;
			printf("material_code_mark = %s\n",material_code_mark.c_str());
			printf("target_prop = %s\n",target_prop);
			//ITKCALL( PROPDESC_set_protection (prop_tag,PROP_write) );
			//char *prop_value=NULL;
			//ITKCALL( AOM_ask_value_string(master_form,target_prop,&prop_value));
			//printf("prop_value=%s\n",prop_value);
			ITKCALL( AOM_set_value_string( master_form, target_prop, material_code_mark.c_str() ) );
			ITKCALL( AOM_save( master_form ) );
			ITKCALL( AOM_unlock( master_form ) );
			//fixed_prop
			char temp_code[64]="";
			strncpy(temp_code,material_code_mark.c_str(),pre_len);
			strcat(temp_code,"\0");
			//TC8==============
			ITKCALL(AOM_load (master_form) );
			//ITKCALL( AOM_unlock( master_form ) );
			//ITKCALL( AOM_lock( master_form ) );
			//ITKCALL( PROPDESC_set_protection (prop_tag,PROP_write));
			ITKCALL( AOM_set_value_string( master_form, fixed_prop, temp_code ) );
			ITKCALL( AOM_save( master_form ) );
			ITKCALL( AOM_unlock( master_form ) );
		}
		else
		{
			printf( ("reviewer has no write privilege to add attachment\n" ) );
			return AM_insufficient_access;
		}
	}

	return ITK_ok;
}

