package edu.vt.marian.Document;

import java.io.*;
import java.net.*;
import java.util.*;

import edu.vt.marian.common.*;


/**
    A fixed field in us marc record.
        User can assume a fix field is composed of an integer id and a 
        string data.
    @author Jianxin Zhao (jxzhao@csgrad.cs.vt.edu)
    @author Robert France (france@vt.edu)

*/

public class MarcFixField
{
    /** the id of this field
    */
    private int id;

    /** the data of this field
    */
    private String data;

    /** just used for debugging
    */
    Debug debug;

    /** Device for mapping ANSEL (and some ASCII) characters to XML entities.
     */
    protected EntityMap xmlMap;

	
    /**
        Create a MarcFixField object with no data.
        @param    id --- this will be the id of this object
        @param    debug -- used for debugging
    */      
    public MarcFixField(int fieldID, EntityMap xMap, Debug d)
    {
        debug = d;
		xmlMap = xMap;
        id = fieldID;
    }


    /**
        Create a MarcFixField object from the parameters id and data .
        @param    fieldID -- the MARC field id of this object
        @param    dataStr -- the data of this object, ASSUMED to be in
						ASCII/ANSEL encoding.
        @param    debug -- used for debugging
    */      
    public MarcFixField(int fieldID, String dataStr, EntityMap xMap, Debug d)
    {
        debug = d;
        xmlMap = xMap;
        data = dataStr;
        id = fieldID;
    }

	/**
        Instantiate this object from an XML stream.
        @param	in -- a BufferedReader (String or InputStream, presumably) from which
			to read the field in OAI MARC XML format.
        @return    OK -- everything jake.
        <BR>    IO_ERROR or PARSE_ERROR -- problems.
        <P>
        <B>NOTE:</B>  Expects opening tag to already be read; eats closing tag.
    */      
    public int setFromXml(BufferedReader in)
    {
        try { 
            data = xmlMap.getStringFromEntityReader(in);
        } catch( Exception e )
        {
            debug.dumpTrace("MarcFixField.setFromXml(): input problem in middle of field.");
            return( ReturnCodes.IO_ERROR );
        }
        if ( ( (data.charAt(0) == '\'') && (data.charAt(data.length()-1) == '\'') ) ||
             ( (data.charAt(0) == '"') && (data.charAt(data.length()-1) == '"') ) )
        {	// Expected case:  data quoted to preserve embedded spaces.
            data = data.substring(1, data.length()-1);
        }

        // Accept the last tag and check that it is "</fixfield>".
 		StringBuffer charBuf = new StringBuffer();
        int i;
        try { while ( true ) {
            i = in.read();
            if ( i == -1 )
            {
                debug.dumpTrace("MarcFixField.setFromXml(): EOF in middle of field.");
                return( ReturnCodes.IO_ERROR );
            }
            else if ( i == '>' )
                break;
            else
                charBuf.append((char) i);
        } } catch( Exception e )
        {
            debug.dumpTrace("MarcFixField.setFromXml(): input problem in middle of field.");
            return( ReturnCodes.IO_ERROR );
        }
        String charStr = new String(charBuf);
        if ( ! "/fixfield".equals(charStr) )
        {
            debug.dumpTrace("MarcFixField.setFromXml(): tag in field other than </fixfield>: <" + charBuf + ">.");
            return( ReturnCodes.IO_ERROR );
        }

     return( ReturnCodes.OK );
    }


    /**
        Send this field to an output stream in the form of OAI XML.
        @param  out -- a BufferedWriter (String or InputStream, presumably) to which
                        to write the next record in OAI MARC XML format.
        @return    OK -- everything jake.
        <BR>    INVALID_INPUT or PARSE_ERROR -- problems.
    */
    public int presentAsXml(BufferedWriter out) throws IOException
    {
        out.write("<fixfield id=\"" + id + "\">\"");
        xmlMap.mapStringToEntities(data, out);		// Note:  field string is always ASCII,
        out.write("\"</fixfield>");					//  not ANSEL, and includes no '<'
        return( ReturnCodes.OK );					//  chars, so no translation needed.
    }



    /**
        Return the id of this object.
        @return    the id of this object as an integer
    */      
    public int getID()
    {
        return id;
    }


    /**
        Return the field string itself.
        @return    the data of this object as a string
    */      
    public String getData()
    {
        return data;
    }

}

