package edu.vt.marian.Document;
import java.io.*;
import java.net.*;
import java.util.*;
import edu.vt.marian.common.*;
/**
A "variable field" in a US MARC record. The user can assume a variable
field is composed of an integer id, two one-character
indicators and at least one subfield.
@author Robert France
@author Jianxin (Jason) Zhao (jxzhao@csgrad.cs.vt.edu)
*/
public class MarcVarField
{
/** The USMARC field id.
*/
protected int id;
/** Indicator characters: see MARC documentation.
*/
protected char indicator1;
protected char indicator2;
/** the USMARC tape format subfield separator character.
*/
protected final static String subfield_separator = "\037";
/** all the subfields of this variable field
*/
protected Vector subfields;
/** just used for debugging
*/
protected Debug debug;
/** Device for mapping ANSEL (and some ASCII) characters to XML entities.
*/
protected EntityMap xmlMap;
/**
Create a MarcVarField object from a field ID and a segment
of a MARC tape format record.
@param id --- this will be the id of this object
@param tapeFormat -- this string contains the indicators and
all the subfields in US MARC tape format.
@param debug -- used for debugging
*/
public MarcVarField(int fieldId, EntityMap xMap, Debug dbg)
{
debug = dbg;
id = fieldId;
xmlMap = xMap;
subfields = null; // Signal for an invalid field.
}
public void setIndicators(char ind1, char ind2)
{
indicator1 = ind1;
indicator2 = ind2;
}
/**
Set this object from a segment of a MARC tape format record.
@param tapeFormat -- this string contains
all the subfields in US MARC tape format.
@param debug -- used for debugging
*/
public int setFromTapeFormat(String tapeFormat)
{
if ((tapeFormat == null) || (tapeFormat.length() < 2))
{
debug.dumpTrace("MarcVarField.setFromTapeFormat(): tape format string is invalid.");
return( ReturnCodes.BAD_PARAMS );
}
// parse indicators
setIndicators(tapeFormat.charAt(0), tapeFormat.charAt(1));
// Analyze subfields.
subfields = new Vector();
MarcSubField msf = null;
StringTokenizer st = new StringTokenizer(tapeFormat.substring(2),
subfield_separator);
String s = null;
while (st.hasMoreTokens())
{
// possible next subfield
s = st.nextToken();
if (s.length() <= 1)
{
// subfield length should be at least 2
debug.dumpTrace("MarcVarField.setFromTapeFormat(): subfield length (" +
s.length() + ") not long enough in '" + tapeFormat + "'.");
return( ReturnCodes.BAD_PARAMS );
}
else
{
msf = new MarcSubField(s.charAt(0), s.substring(1), xmlMap, debug);
subfields.addElement(msf);
}
}
// all the subfields have been parsed
return( ReturnCodes.OK );
}
/**
Set this object from an OA XML MARC string.
@param in -- a BufferedReader containing the contents
of a VarField (i.e., all the subfields but
not the initial tag) in OA XML format.
@return OK -- everything jake.
IO_ERROR or PARSE_ERROR -- problems.
NOTE: Expects opening tag to already be read; eats closing tag.
*/
public int setFromXml(BufferedReader in) throws IOException
{
if ( in == null)
return( ReturnCodes.BAD_PARAMS );
subfields = new Vector();
Vector bindings;
while ( true )
{
if ( (bindings = XmlDoc.acceptTag(in)) == null )
{
debug.dumpTrace("MarcVarField.setFromXml(): missing tag in field " + id + ".");
return( ReturnCodes.PARSE_ERROR );
}
if ( ((String) bindings.elementAt(0)).equals("/varfield") )
{
if ( subfields.size() == 0 )
{
debug.dumpTrace("MarcVarField.setFromXml(): no subfields for field " +
id + ".");
subfields = null; // Mark invalid.
return( ReturnCodes.IO_ERROR );
}
else
return( ReturnCodes.OK );
}
// Only valid nested tag here is "
INVALID_INPUT or PARSE_ERROR -- problems.
*/
public int presentAsTapeFormat(BufferedWriter out) throws IOException
{
int Err;
out.write(indicator1);
out.write(indicator2);
Enumeration subfld = subfields.elements();
try { while ( true )
{
MarcSubField sf = (MarcSubField) subfld.nextElement();
out.write(subfield_separator);
out.write(sf.getLabel());
if ( (Err = sf.present(DigInfObj.ANSEL, out)) != ReturnCodes.OK )
return( Err );
} } catch( NoSuchElementException e) {};
return( ReturnCodes.OK );
}
/**
Send this 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 OA_MARC XML format.
@return OK -- everything jake.
INVALID_INPUT or PARSE_ERROR -- problems.
*/
public int presentAsXml(BufferedWriter out) throws IOException
{
if ( subfields == null) // Invalid field
{
return( ReturnCodes.NO_CAN_DO );
}
out.write("