2525import org .metafacture .framework .annotations .Out ;
2626import org .metafacture .framework .helpers .DefaultStreamPipe ;
2727
28+ import java .util .Arrays ;
2829import java .util .Collections ;
30+ import java .util .function .Function ;
2931
3032/**
3133 * Encodes a stream into MARCXML.
4042@ FluxCommand ("encode-marcxml" )
4143public final class MarcXmlEncoder extends DefaultStreamPipe <ObjectReceiver <String >> {
4244
43- private static final String NAMESPACE = "http://www.loc.gov/MARC21/slim" ;
44- private static final String NAMESPACE_NAME = "marc" ;
45- /*package-private*/ static final String NAMESPACE_PREFIX = NAMESPACE_NAME + ":" ;
46- private static final String NAMESPACE_SUFFIX = ":" + NAMESPACE_NAME ;
45+ private enum Tag {
4746
48- private static final String SCHEMA_ATTRIBUTES = " xmlns:xsi=\" http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\" " + NAMESPACE + " http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd\" " ;
47+ collection (" xmlns%s=\" " + NAMESPACE + "\" %s" ),
48+ controlfield (" tag=\" %s\" " ),
49+ datafield (" tag=\" %s\" ind1=\" %s\" ind2=\" %s\" " ),
50+ leader ("" ),
51+ record ("" ),
52+ subfield (" code=\" %s\" " );
4953
50- /*package- private*/ static final String ROOT_OPEN_TEMPLATE = "<%scollection xmlns%s= \" " + NAMESPACE + " \" %s>" ;
51- private static final String ROOT_CLOSE_TEMPLATE = "</%scollection >" ;
54+ private static final String OPEN_TEMPLATE = "<%%s%s %s>" ;
55+ private static final String CLOSE_TEMPLATE = "</%%s%s >" ;
5256
53- private static final String RECORD_OPEN_TEMPLATE = "<%srecord>" ;
54- private static final String RECORD_CLOSE_TEMPLATE = "</%srecord>" ;
57+ private final String openTemplate ;
58+ private final String closeTemplate ;
5559
56- private static final String ATTRIBUTE_TEMPLATE = " %s=\" %s\" " ;
60+ Tag (final String template ) {
61+ openTemplate = String .format (OPEN_TEMPLATE , name (), template );
62+ closeTemplate = String .format (CLOSE_TEMPLATE , name ());
63+ }
64+
65+ public String open (final Object [] args ) {
66+ return String .format (openTemplate , args );
67+ }
68+
69+ public String close (final Object [] args ) {
70+ return String .format (closeTemplate , args );
71+ }
5772
58- private static final String CONTROLFIELD_OPEN_TEMPLATE = "<%scontrolfield tag=\" %s\" >" ;
59- private static final String CONTROLFIELD_CLOSE_TEMPLATE = "</%scontrolfield>" ;
73+ }
6074
61- private static final String DATAFIELD_OPEN_TEMPLATE = "<%sdatafield tag=\" %s\" ind1=\" %s\" ind2=\" %s\" >" ;
62- private static final String DATAFIELD_CLOSE_TEMPLATE = "</%sdatafield>" ;
75+ private static final String NAMESPACE = "http://www.loc.gov/MARC21/slim" ;
76+ private static final String NAMESPACE_NAME = "marc" ;
77+ private static final String NAMESPACE_PREFIX = NAMESPACE_NAME + ":" ;
78+ private static final String NAMESPACE_SUFFIX = ":" + NAMESPACE_NAME ;
6379
64- private static final String SUBFIELD_OPEN_TEMPLATE = "<%ssubfield code=\" %s\" >" ;
65- private static final String SUBFIELD_CLOSE_TEMPLATE = "</%ssubfield>" ;
80+ private static final String SCHEMA_ATTRIBUTES = " xmlns:xsi=\" http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\" " + NAMESPACE + " http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd\" " ;
6681
67- private static final String LEADER_TEMPLATE = "<%sleader>%s</%sleader> " ;
82+ private static final String ATTRIBUTE_TEMPLATE = " %s= \" %s \" " ;
6883
6984 private static final String NEW_LINE = "\n " ;
7085 private static final String INDENT = "\t " ;
@@ -90,7 +105,7 @@ public final class MarcXmlEncoder extends DefaultStreamPipe<ObjectReceiver<Strin
90105 private String xmlEncoding ;
91106
92107 private boolean emitNamespace ;
93- private String namespacePrefix ;
108+ private Object [] namespacePrefix ;
94109
95110 private String currentEntity ;
96111 private int indentationLevel ;
@@ -115,7 +130,7 @@ public MarcXmlEncoder() {
115130
116131 public void setEmitNamespace (final boolean emitNamespace ) {
117132 this .emitNamespace = emitNamespace ;
118- namespacePrefix = emitNamespace ? NAMESPACE_PREFIX : EMPTY ;
133+ namespacePrefix = new Object []{ emitNamespace ? NAMESPACE_PREFIX : EMPTY } ;
119134 }
120135
121136 public void omitXmlDeclaration (final boolean currentOmitXmlDeclaration ) {
@@ -147,16 +162,14 @@ public void startRecord(final String identifier) {
147162 writeHeader ();
148163 prettyPrintNewLine ();
149164 }
150- writeRaw (String .format (ROOT_OPEN_TEMPLATE , namespacePrefix ,
151- emitNamespace ? NAMESPACE_SUFFIX : EMPTY ,
152- emitNamespace ? SCHEMA_ATTRIBUTES : EMPTY ));
165+ writeTag (Tag .collection ::open , emitNamespace ? NAMESPACE_SUFFIX : EMPTY , emitNamespace ? SCHEMA_ATTRIBUTES : EMPTY );
153166 prettyPrintNewLine ();
154167 incrementIndentationLevel ();
155168 }
156169 atStreamStart = false ;
157170
158171 prettyPrintIndentation ();
159- writeRaw ( String . format ( RECORD_OPEN_TEMPLATE , namespacePrefix ) );
172+ writeTag ( Tag . record :: open );
160173 recordAttributeOffset = builder .length () - 1 ;
161174 prettyPrintNewLine ();
162175
@@ -167,7 +180,7 @@ public void startRecord(final String identifier) {
167180 public void endRecord () {
168181 decrementIndentationLevel ();
169182 prettyPrintIndentation ();
170- writeRaw ( String . format ( RECORD_CLOSE_TEMPLATE , namespacePrefix ) );
183+ writeTag ( Tag . record :: close );
171184 prettyPrintNewLine ();
172185 sendAndClearData ();
173186 }
@@ -186,7 +199,7 @@ public void startEntity(final String name) {
186199 final String ind1 = name .substring (IND1_BEGIN , IND1_END );
187200 final String ind2 = name .substring (IND2_BEGIN , IND2_END );
188201 prettyPrintIndentation ();
189- writeRaw ( String . format ( DATAFIELD_OPEN_TEMPLATE , namespacePrefix , tag , ind1 , ind2 ) );
202+ writeTag ( Tag . datafield :: open , tag , ind1 , ind2 );
190203 prettyPrintNewLine ();
191204 incrementIndentationLevel ();
192205 }
@@ -197,7 +210,7 @@ public void endEntity() {
197210 if (!currentEntity .equals (Marc21EventNames .LEADER_ENTITY )) {
198211 decrementIndentationLevel ();
199212 prettyPrintIndentation ();
200- writeRaw ( String . format ( DATAFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
213+ writeTag ( Tag . datafield :: close );
201214 prettyPrintNewLine ();
202215 }
203216 currentEntity = "" ;
@@ -213,19 +226,19 @@ public void literal(final String name, final String value) {
213226 }
214227 else if (!writeLeader (name , value )) {
215228 prettyPrintIndentation ();
216- writeRaw ( String . format ( CONTROLFIELD_OPEN_TEMPLATE , namespacePrefix , name ) );
229+ writeTag ( Tag . controlfield :: open , name );
217230 if (value != null ) {
218231 writeEscaped (value .trim ());
219232 }
220- writeRaw ( String . format ( CONTROLFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
233+ writeTag ( Tag . controlfield :: close );
221234 prettyPrintNewLine ();
222235 }
223236 }
224237 else if (!writeLeader (currentEntity , value )) {
225238 prettyPrintIndentation ();
226- writeRaw ( String . format ( SUBFIELD_OPEN_TEMPLATE , namespacePrefix , name ) );
239+ writeTag ( Tag . subfield :: open , name );
227240 writeEscaped (value .trim ());
228- writeRaw ( String . format ( SUBFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
241+ writeTag ( Tag . subfield :: close );
229242 prettyPrintNewLine ();
230243 }
231244 }
@@ -262,7 +275,7 @@ private void writeHeader() {
262275
263276 /** Closes the root tag */
264277 private void writeFooter () {
265- writeRaw ( String . format ( ROOT_CLOSE_TEMPLATE , namespacePrefix ) );
278+ writeTag ( Tag . collection :: close );
266279 }
267280
268281 /** Writes a unescaped sequence */
@@ -278,7 +291,9 @@ private void writeEscaped(final String str) {
278291 private boolean writeLeader (final String name , final String value ) {
279292 if (name .equals (Marc21EventNames .LEADER_ENTITY )) {
280293 prettyPrintIndentation ();
281- writeRaw (String .format (LEADER_TEMPLATE , namespacePrefix , value , namespacePrefix ));
294+ writeTag (Tag .leader ::open );
295+ writeRaw (value );
296+ writeTag (Tag .leader ::close );
282297 prettyPrintNewLine ();
283298
284299 return true ;
@@ -288,6 +303,12 @@ private boolean writeLeader(final String name, final String value) {
288303 }
289304 }
290305
306+ private void writeTag (final Function <Object [], String > function , final Object ... args ) {
307+ final Object [] allArgs = Arrays .copyOf (namespacePrefix , namespacePrefix .length + args .length );
308+ System .arraycopy (args , 0 , allArgs , namespacePrefix .length , args .length );
309+ writeRaw (function .apply (allArgs ));
310+ }
311+
291312 private void prettyPrintIndentation () {
292313 if (formatted ) {
293314 final String prefix = String .join ("" , Collections .nCopies (indentationLevel , INDENT ));
0 commit comments