25
25
import org .metafacture .framework .annotations .Out ;
26
26
import org .metafacture .framework .helpers .DefaultStreamPipe ;
27
27
28
+ import java .util .Arrays ;
28
29
import java .util .Collections ;
30
+ import java .util .function .Function ;
29
31
30
32
/**
31
33
* Encodes a stream into MARCXML.
40
42
@ FluxCommand ("encode-marcxml" )
41
43
public final class MarcXmlEncoder extends DefaultStreamPipe <ObjectReceiver <String >> {
42
44
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 {
47
46
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\" " );
49
53
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 >" ;
52
56
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 ;
55
59
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
+ }
57
72
58
- private static final String CONTROLFIELD_OPEN_TEMPLATE = "<%scontrolfield tag=\" %s\" >" ;
59
- private static final String CONTROLFIELD_CLOSE_TEMPLATE = "</%scontrolfield>" ;
73
+ }
60
74
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 ;
63
79
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\" " ;
66
81
67
- private static final String LEADER_TEMPLATE = "<%sleader>%s</%sleader> " ;
82
+ private static final String ATTRIBUTE_TEMPLATE = " %s= \" %s \" " ;
68
83
69
84
private static final String NEW_LINE = "\n " ;
70
85
private static final String INDENT = "\t " ;
@@ -90,7 +105,7 @@ public final class MarcXmlEncoder extends DefaultStreamPipe<ObjectReceiver<Strin
90
105
private String xmlEncoding ;
91
106
92
107
private boolean emitNamespace ;
93
- private String namespacePrefix ;
108
+ private Object [] namespacePrefix ;
94
109
95
110
private String currentEntity ;
96
111
private int indentationLevel ;
@@ -115,7 +130,7 @@ public MarcXmlEncoder() {
115
130
116
131
public void setEmitNamespace (final boolean emitNamespace ) {
117
132
this .emitNamespace = emitNamespace ;
118
- namespacePrefix = emitNamespace ? NAMESPACE_PREFIX : EMPTY ;
133
+ namespacePrefix = new Object []{ emitNamespace ? NAMESPACE_PREFIX : EMPTY } ;
119
134
}
120
135
121
136
public void omitXmlDeclaration (final boolean currentOmitXmlDeclaration ) {
@@ -147,16 +162,14 @@ public void startRecord(final String identifier) {
147
162
writeHeader ();
148
163
prettyPrintNewLine ();
149
164
}
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 );
153
166
prettyPrintNewLine ();
154
167
incrementIndentationLevel ();
155
168
}
156
169
atStreamStart = false ;
157
170
158
171
prettyPrintIndentation ();
159
- writeRaw ( String . format ( RECORD_OPEN_TEMPLATE , namespacePrefix ) );
172
+ writeTag ( Tag . record :: open );
160
173
recordAttributeOffset = builder .length () - 1 ;
161
174
prettyPrintNewLine ();
162
175
@@ -167,7 +180,7 @@ public void startRecord(final String identifier) {
167
180
public void endRecord () {
168
181
decrementIndentationLevel ();
169
182
prettyPrintIndentation ();
170
- writeRaw ( String . format ( RECORD_CLOSE_TEMPLATE , namespacePrefix ) );
183
+ writeTag ( Tag . record :: close );
171
184
prettyPrintNewLine ();
172
185
sendAndClearData ();
173
186
}
@@ -186,7 +199,7 @@ public void startEntity(final String name) {
186
199
final String ind1 = name .substring (IND1_BEGIN , IND1_END );
187
200
final String ind2 = name .substring (IND2_BEGIN , IND2_END );
188
201
prettyPrintIndentation ();
189
- writeRaw ( String . format ( DATAFIELD_OPEN_TEMPLATE , namespacePrefix , tag , ind1 , ind2 ) );
202
+ writeTag ( Tag . datafield :: open , tag , ind1 , ind2 );
190
203
prettyPrintNewLine ();
191
204
incrementIndentationLevel ();
192
205
}
@@ -197,7 +210,7 @@ public void endEntity() {
197
210
if (!currentEntity .equals (Marc21EventNames .LEADER_ENTITY )) {
198
211
decrementIndentationLevel ();
199
212
prettyPrintIndentation ();
200
- writeRaw ( String . format ( DATAFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
213
+ writeTag ( Tag . datafield :: close );
201
214
prettyPrintNewLine ();
202
215
}
203
216
currentEntity = "" ;
@@ -213,19 +226,19 @@ public void literal(final String name, final String value) {
213
226
}
214
227
else if (!writeLeader (name , value )) {
215
228
prettyPrintIndentation ();
216
- writeRaw ( String . format ( CONTROLFIELD_OPEN_TEMPLATE , namespacePrefix , name ) );
229
+ writeTag ( Tag . controlfield :: open , name );
217
230
if (value != null ) {
218
231
writeEscaped (value .trim ());
219
232
}
220
- writeRaw ( String . format ( CONTROLFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
233
+ writeTag ( Tag . controlfield :: close );
221
234
prettyPrintNewLine ();
222
235
}
223
236
}
224
237
else if (!writeLeader (currentEntity , value )) {
225
238
prettyPrintIndentation ();
226
- writeRaw ( String . format ( SUBFIELD_OPEN_TEMPLATE , namespacePrefix , name ) );
239
+ writeTag ( Tag . subfield :: open , name );
227
240
writeEscaped (value .trim ());
228
- writeRaw ( String . format ( SUBFIELD_CLOSE_TEMPLATE , namespacePrefix ) );
241
+ writeTag ( Tag . subfield :: close );
229
242
prettyPrintNewLine ();
230
243
}
231
244
}
@@ -262,7 +275,7 @@ private void writeHeader() {
262
275
263
276
/** Closes the root tag */
264
277
private void writeFooter () {
265
- writeRaw ( String . format ( ROOT_CLOSE_TEMPLATE , namespacePrefix ) );
278
+ writeTag ( Tag . collection :: close );
266
279
}
267
280
268
281
/** Writes a unescaped sequence */
@@ -278,7 +291,9 @@ private void writeEscaped(final String str) {
278
291
private boolean writeLeader (final String name , final String value ) {
279
292
if (name .equals (Marc21EventNames .LEADER_ENTITY )) {
280
293
prettyPrintIndentation ();
281
- writeRaw (String .format (LEADER_TEMPLATE , namespacePrefix , value , namespacePrefix ));
294
+ writeTag (Tag .leader ::open );
295
+ writeRaw (value );
296
+ writeTag (Tag .leader ::close );
282
297
prettyPrintNewLine ();
283
298
284
299
return true ;
@@ -288,6 +303,12 @@ private boolean writeLeader(final String name, final String value) {
288
303
}
289
304
}
290
305
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
+
291
312
private void prettyPrintIndentation () {
292
313
if (formatted ) {
293
314
final String prefix = String .join ("" , Collections .nCopies (indentationLevel , INDENT ));
0 commit comments