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 "". if ( ( ! ((String) bindings.elementAt(0)).equals("subfield") ) || ( ! ((String) bindings.elementAt(1)).equals("label") ) ) { debug.dumpTrace("MarcVarField.setFromXml(): malformed subfield tag in field " + id + "."); subfields = null; // Mark invalid. return( ReturnCodes.PARSE_ERROR ); } char label = ((String) bindings.elementAt(2)).charAt(0); String subFieldStr = xmlMap.getStringFromEntityReader(in); MarcSubField msf = new MarcSubField(label, subFieldStr, xmlMap, debug); subfields.addElement(msf); if ( (bindings = XmlDoc.acceptPreppedTag(in)) == null ) { debug.dumpTrace("MarcVarField.setFromXml(): no tag in field " + id + "."); subfields = null; // Mark invalid. return( ReturnCodes.PARSE_ERROR ); } if ( ! ((String) bindings.elementAt(0)).equals("/subfield") ) { debug.dumpTrace("MarcVarField.setFromXml(): unexpected tag <" + (String) bindings.elementAt(0) + "> in field " + id + "."); subfields = null; // Mark invalid. return( ReturnCodes.PARSE_ERROR ); } } } /** 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 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(""); Enumeration subfld = subfields.elements(); int Err; try { while ( true ) { MarcSubField sf = (MarcSubField) subfld.nextElement(); if ( (Err = sf.present( DigInfObj.XML, out)) != ReturnCodes.OK ) return(Err); out.newLine(); } } catch( NoSuchElementException e) {}; out.write(""); return( ReturnCodes.OK ); } /** return the id of this object @return the id of this object as an integer */ public int getID() { if ( subfields == null) // Invalid field { return( ReturnCodes.NO_CAN_DO ); } return id; } /** return the number of subfields in this object @return the number of subfields in this object as an integer */ public int getNumberSubfields() { if ( subfields == null) // Invalid field { return( ReturnCodes.NO_CAN_DO ); } return subfields.size(); } /** return the indexth subfield of this object @param index -- used to search the subfields vector @return a MarcSubField object or null if the index is not invalid */ public MarcSubField getSubfieldByIndex(int index) { if ( subfields == null) // Invalid field { return( null ); } if ((index < 0) || (index >= subfields.size())) { // invalid index debug.dumpTrace("MarcVarField.getSubfieldByIndex(): index is not valid."); return null; } // valid index, return the corresponding subfield return (MarcSubField) subfields.elementAt(index); } /** return all the subfields in this object with the specified label @param label -- used to search the subfields vector @return a vector containing all the subfields in this object that have the specified label. */ public Vector getSubfieldsByLabel(char label) { if ( subfields == null) // Invalid field { return( null ); } Vector msfs = new Vector(); MarcSubField msf = null; for (int i = 0; i < subfields.size(); i++) { msf = (MarcSubField) subfields.elementAt(i); if (msf.getLabel() == label) { msfs.addElement(msf); } } return msfs; } /** return the indicators of this object @return the indicators of this object as a string */ public String getIndicators() { if ( subfields == null) // Invalid field { return( null ); } char [] indChars = new char [2]; indChars[0] = indicator1; indChars[1] = indicator2; return( new String(indChars) ); } }