package daruma.storage_manager.type_definition;

import daruma.storage_manager.type_definition.TypeDefinition;
import daruma.storage_manager.type_definition.TypedInstance;
import daruma.storage_manager.type_definition.TypeException;
import daruma.storage_manager.StorageManager;
import daruma.storage_manager.StorageException;
import daruma.geometry.TransformationContext;
import daruma.sql.SQLDataType;
import daruma.sql.TableColumn;
import daruma.sql.TableColumnDefinition;
import daruma.xml.UniversalName;
import daruma.xml.SimpleXPath;
import daruma.xml.util.ElementUtil;
import daruma.util.Pair;
import daruma.util.LogWriter;

import org.w3c.dom.Element;
import org.w3c.dom.Document;

import java.util.List;
import java.util.ArrayList;


public abstract class AbstractSingleTypeDefinition extends TypeDefinition
{
	public	AbstractSingleTypeDefinition()
	{
		super( false , false );
	}

	@Override
	public	abstract SQLDataType	getSingleSQLDataType();

	public	abstract String		parseValue( String  value )
							throws TypeException;

	public	Pair<TypedInstance, Integer>
				createInstance( Element  element ,
						ElementName  topLevelElement ,
						SimpleXPath  path ,
						StorageManager  storage ,
						int  elementIndex )
							  throws TypeException
	{
		LogWriter.qwrite("DEBUG",  this.getClass().getName(),
				 ": createInstance()" );

		String	value = null;

		try
		{
			value = this.parseValue
				( ElementUtil
				  .getChildNodesWholeText( element ) );
		}
		catch( TypeException  e )
		{
			throw new TypeException( e.getMessage() , e );
		}


		String	columnName;
		if ( path == null )
		{
			columnName = 
			    ColumnNameFactory
			    .getTopLevelElementColumnName();
		}
		else
		{
			SimpleXPath	newPath = new SimpleXPath( path );

			newPath.add( new UniversalName
				     ( element.getNamespaceURI() ,
				       element.getLocalName() ) );

			try
			{
				columnName
				 = storage.getShortXPathStringForDB( newPath );
			}
			catch( StorageException  e )
			{
				throw new TypeException( e );
			}
		}

		TableColumn	column;
		column = new TableColumn( new TableColumnDefinition
					  ( columnName ,
					    this.getSingleSQLDataType() ) ,
					  value );

		List<TableColumn>  columnList = new ArrayList<TableColumn>();
		columnList.add( column );

		return( new Pair<TypedInstance, Integer>
			( new TypedInstance( columnList , this ) , -1 ) );
	}

	@Override
	public	 int	convertToXMLElement( Element  element ,
					     Document  doc ,
					     StorageManager  storage ,
					     TransformationContext  trans ,
					     List<TableColumn>  columns ,
					     int  index ,
					     long  id ) throws TypeException
	{
		LogWriter.qwrite( "DEBUG",
				  this.getClass().getName(),
				  ".convertToXMLElement()" );

		if ( index >= columns.size() )
		{
			throw new TypeException
			  ( "internal error in " + this.getClass().getName()
			    + ": unexpected instantiation" );
		}

		String	value = columns.get( index ).getValue();

		if ( value != null )
		{
			element.appendChild( doc.createTextNode
					     ( value ) );
		}

		return( index + 1 );
	}
}
