<?php

class Xoonips_ImportItemType {

	public $itemtype_obj = array();
	public $group_obj = array();
	public $detail_obj = array();
	public $relation_obj = array();
	public $group_arr = array();
	public $detail_arr = array();
	public $relation_arr = array();
	public $error_messages = array();

	function setItemtypeObj($key, $value){
		$this -> itemtype_obj[$key] = $value;
	}

	function getItemtypeObj(){
		return $this -> itemtype_obj;
	}

	function addGroupObj($group){
		$this -> group_obj[] = $group;
	}

	function getGroupObj(){
		return $this -> group_obj;
	}

	function setGroupArr($key, $value){
		$this -> group_arr[$key] = $value;
	}

	function addDetailObj($detail){
		$this -> detail_obj[] = $detail;
	}

	function getDetailObj(){
		return $this -> detail_obj;
	}

	function setDetailArr($key, $value){
		$this -> detail_arr[$key] = $value;
	}

	function addRelationObj($relation){
		$this -> relation_obj[] = $relation;
	}

	function getRelationObj(){
		return $this -> relation_obj;
	}

	function setRelationArr($key, $value){
		$this -> relation_arr[$key] = $value;
	}

	function setErrors($err_code, $err_str){
		$this -> error_messages[] = $err_code . ":" . $err_str;
	}

	function getErrors(){
		return $this -> error_messages;
	}
}

class Xoonips_ImportItemTypeHandler{

	// current import itemtype object for parseXml
	private $import_itemtype = null;

	// xml parser object
	private $parser = null;

	// current cdata
	private $cdata = null;

	// xml tag stack
	private $tag_stack = array();

	// itemtype attribute
	private $itemtype_attr = array(
		"item_type_id" =>array(1, 'i', 8),
		"preselect" =>array(1, 'i', 1),
		"released" =>array(1, 'i', 1),
		"weight" =>array(1, 'i', 3),
		"name" =>array(1, 's', 30),
		"description" =>array(0, 's', 255),
		"icon" =>array(0, 's', 255),
		"mime_type" =>array(0, 's', 255),
		"template" =>array(0, 's', -1),
		"update_id" =>array(0, 'i', 8),
	);

	// itemtype group attribute
	private $group_attr = array(
		"group_id" =>array(1, 'i', 8),
		"released" =>array(1, 'i', 1),
		"preselect" =>array(1, 'i', 1),
		"item_type_id" =>array(1, 'i', 8),
		"name" =>array(1, 's', 255),
		"xml" =>array(1, 's', 30),
		"weight" =>array(1, 'i', 3),
		"occurrence" =>array(1, 'i', 1),
		"update_id" =>array(0, 'i', 8),
	);

	// itemtype detail attribute
	private $detail_attr = array(
		"item_field_detail_id" =>array(1, 'i', 8),
		"released" =>array(1, 'i', 1),
		"preselect" =>array(1, 'i', 1),
		"table_name" =>array(1, 's', 50),
		"column_name" =>array(1, 's', 50),
		"item_type_id" =>array(1, 'i', 8),
		"group_id" =>array(1, 'i', 8),
		"weight" =>array(1, 'i', 3),
		"name" =>array(1, 's', 255),
		"xml" =>array(1, 's', 30),
		"view_type_id" =>array(1, 'i', 8),
		"data_type_id" =>array(1, 'i', 8),
		"data_length" =>array(1, 'i', 5),
		"data_decimal_places" =>array(1, 'i', 2),
		"default_value" =>array(0, 's', 30),
		"list" =>array(0, 's', 50),
		"essential" =>array(1, 'i', 1),
		"detail_display" =>array(1, 'i', 1),
		"detail_target" =>array(1, 'i', 1),
		"scope_search" =>array(1, 'i', 1),
		"nondisplay" =>array(1, 'i', 1),
		"update_id" =>array(0, 'i', 8),
	);

	// relation detail attribute
	private $relation_attr = array(
		"seq_id" =>array(1, 'i', 8),
		"released" =>array(1, 'i', 1),
		"complement_id" =>array(1, 'i', 3),
		"item_type_id" =>array(1, 'i', 8),
		"base_item_field_detail_id" =>array(1, 'i', 8),
		"complement_detail_id" =>array(1, 'i', 3),
		"item_field_detail_id" =>array(1, 'i', 8),
		"update_id" =>array(0, 'i', 8),
	);

	public function Xoonips_ImportItemTypeHandler(){
	}

	public function create(){
		return new Xoonips_ImportItemType();
	}

	/**
	 * create Xoonips_ImportItemType object from XML
	 * @param $xml string xml text to parse
	 * @return XooNIpsImportItem
	 */
	public function &parseXml($xml){
		$this -> import_itemtype = $this -> create();

		$this -> parser = xml_parser_create();
		xml_set_character_data_handler($this -> parser, 'xmlCdataHandler' );
		xml_set_element_handler($this -> parser,
                                'xmlStartElementHandler', 
                                'xmlEndElementHandler' );
		xml_set_object($this -> parser, $this);

		xml_parse($this -> parser, $xml);

		return $this -> import_itemtype;
	}

	/**
	 *
	 * @param
	 * @return void
	 */
	public function xmlStartElementHandler( $parser , $name , $attribs ){
		array_push( $this -> tag_stack, $name );
		$this -> cdata = '';
		switch( implode( '/', $this -> tag_stack ) ){
			case 'ITEMTYPE':
			case 'ITEMTYPE/GROUP':
			case "ITEMTYPE/GROUP/DETAIL":
			case 'ITEMTYPE/RELATION':
				if( !isset( $attribs['ID'] ) ) {
					$this -> import_itemtype -> setErrors(
					'E0006', "ID is not declared"
					. $this -> getParserErrorAt() );
				}
				if( empty( $attribs['ID'] ) ) {
					$this -> import_itemtype -> setErrors(
					'E0007', "ID is empty"
					. $this -> getParserErrorAt() );
				} else if ( !ctype_digit( $attribs['ID'] ) ) {
					$this -> import_itemtype -> setErrors(
					'E0007', "ID is not integer"
					. $this -> getParserErrorAt() );
				}
				break;
		}
	}

	/**
	 *
	 * @param
	 * @return void
	 */
	public function xmlCdataHandler( $parser,$data ){
		$this -> cdata .= $data;
	}

	/**
	 *
	 * @param
	 * @return void
	 */
	public function xmlEndElementHandler( $parser ,$name ){
		$cdata = Xoonips_Utils::decodeUtf8($this->cdata, Xoonips_Utils::getServerCharset(), 'n');
		switch( implode( '/', $this -> tag_stack ) ){
			case "ITEMTYPE/GROUP":
				$this -> import_itemtype -> addGroupObj( $this->import_itemtype->group_arr );
				break;
			case "ITEMTYPE/GROUP/DETAIL":
				$this -> import_itemtype -> addDetailObj( $this->import_itemtype->detail_arr );
				break;
			case 'ITEMTYPE/RELATION':
				$this -> import_itemtype -> addRelationObj( $this->import_itemtype->relation_arr );
				break;
			case "ITEMTYPE/".$name:
				$key = strtolower($name);
				$this -> checkParameterError( $cdata, $this->itemtype_attr, $key );
				$this -> import_itemtype -> setItemtypeObj( $key, $cdata );
				break;
			case "ITEMTYPE/GROUP/".$name:
				$key = strtolower($name);
				$this -> checkParameterError( $cdata, $this->group_attr, $key );
				$this -> import_itemtype -> setGroupArr( $key, $cdata );
				break;
			case "ITEMTYPE/GROUP/DETAIL/".$name:
				$key = strtolower($name);
				$this -> checkParameterError( $cdata, $this->detail_attr, $key );
				$this -> import_itemtype -> setDetailArr( $key, $cdata );
				break;
			case "ITEMTYPE/RELATION/".$name:
				$key = strtolower($name);
				$this -> checkParameterError( $cdata, $this->relation_attr, $key );
				$this -> import_itemtype -> setRelationArr( $key, $cdata );
				break;
		}
		array_pop( $this -> tag_stack );
	}

	private function checkParameterError( $data, $attr, $key ){
		if ( isset( $attr[$key] ) ) {
			if ( $data == '' && $attr[$key][0] == 1 ) {
				$this -> import_itemtype -> setErrors(
				'E0007', "$key is empty"
				. $this -> getParserErrorAt() );
			}
			if ( !empty( $data ) && !is_numeric( $data ) && $attr[$key][1] == 'i' ) {
				$this -> import_itemtype -> setErrors(
				'E0007', "$key is not integer"
				. $this -> getParserErrorAt() );
			}
			if ( strlen( $data ) > $attr[$key][2] && $attr[$key][2] > 0) {
				$this -> import_itemtype -> setErrors(
				'E0008', "$key is too long"
				. $this -> getParserErrorAt() );
			}
		} else {
			$this -> import_itemtype -> setErrors(
			'E0019', "$key tag is not found"
			. $this -> getParserErrorAt() );
		}
	}

	private function getParserErrorAt(){
		return " at line ".xml_get_current_line_number( $this -> parser )
		.", column ".xml_get_current_column_number( $this -> parser );
	}
}

