28
28
import java .util .LinkedList ;
29
29
import java .util .List ;
30
30
import java .util .Map ;
31
+ import java .util .regex .Pattern ;
31
32
32
33
import org .metafacture .commons .ResourceUtil ;
33
34
import org .metafacture .framework .FluxCommand ;
48
49
import org .metafacture .metamorph .api .NamedValueReceiver ;
49
50
import org .metafacture .metamorph .api .NamedValueSource ;
50
51
import org .metafacture .metamorph .api .SourceLocation ;
52
+ import org .slf4j .Logger ;
53
+ import org .slf4j .LoggerFactory ;
51
54
import org .xml .sax .InputSource ;
52
55
53
56
/**
64
67
@ FluxCommand ("morph" )
65
68
public final class Metamorph implements StreamPipe <StreamReceiver >, NamedValuePipe , Maps {
66
69
70
+ private static final String ELSE_NESTED_KEYWORD = "_elseNested" ;
67
71
public static final String ELSE_KEYWORD = "_else" ;
72
+ public static final String ELSE_FLATTENED_KEYWORD = "_elseFlattened" ;
68
73
public static final char FEEDBACK_CHAR = '@' ;
69
74
public static final char ESCAPE_CHAR = '\\' ;
70
75
public static final String METADATA = "__meta" ;
@@ -77,8 +82,7 @@ public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePi
77
82
private static final InterceptorFactory NULL_INTERCEPTOR_FACTORY = new NullInterceptorFactory ();
78
83
private static final Map <String , String > NO_VARS = Collections .emptyMap ();
79
84
80
- private final Registry <NamedValueReceiver > dataRegistry =
81
- new WildcardRegistry <>();
85
+ private final Registry <NamedValueReceiver > dataRegistry = new WildcardRegistry <>();
82
86
private final List <NamedValueReceiver > elseSources = new ArrayList <>();
83
87
84
88
private final Map <String , Map <String , String >> maps = new HashMap <>();
@@ -94,6 +98,10 @@ public final class Metamorph implements StreamPipe<StreamReceiver>, NamedValuePi
94
98
private MorphErrorHandler errorHandler = new DefaultErrorHandler ();
95
99
private int recordCount ;
96
100
private final List <FlushListener > recordEndListener = new ArrayList <>();
101
+ private boolean elseNested ;
102
+ private boolean elseNestedEntityStarted ;
103
+ private String currentLiteralName ;
104
+ private static final Logger LOG = LoggerFactory .getLogger (Metamorph .class );
97
105
98
106
protected Metamorph () {
99
107
// package private
@@ -114,7 +122,6 @@ public Metamorph(final String morphDef, final InterceptorFactory interceptorFact
114
122
115
123
public Metamorph (final String morphDef , final Map <String , String > vars ,
116
124
final InterceptorFactory interceptorFactory ) {
117
-
118
125
this (getInputSource (morphDef ), vars , interceptorFactory );
119
126
}
120
127
@@ -132,7 +139,6 @@ public Metamorph(final Reader morphDef, final InterceptorFactory interceptorFact
132
139
133
140
public Metamorph (final Reader morphDef , final Map <String , String > vars ,
134
141
final InterceptorFactory interceptorFactory ) {
135
-
136
142
this (new InputSource (morphDef ), vars , interceptorFactory );
137
143
}
138
144
@@ -150,7 +156,6 @@ public Metamorph(final InputStream morphDef, final InterceptorFactory intercepto
150
156
151
157
public Metamorph (final InputStream morphDef , final Map <String , String > vars ,
152
158
final InterceptorFactory interceptorFactory ) {
153
-
154
159
this (new InputSource (morphDef ), vars , interceptorFactory );
155
160
}
156
161
@@ -197,7 +202,7 @@ private void init() {
197
202
flattener .setReceiver (new DefaultStreamReceiver () {
198
203
@ Override
199
204
public void literal (final String name , final String value ) {
200
- dispatch (name , value , getElseSources ());
205
+ dispatch (name , value , getElseSources (), false );
201
206
}
202
207
});
203
208
}
@@ -215,8 +220,17 @@ public void setErrorHandler(final MorphErrorHandler errorHandler) {
215
220
}
216
221
217
222
protected void registerNamedValueReceiver (final String source , final NamedValueReceiver data ) {
218
- if (ELSE_KEYWORD .equals (source )) {
219
- elseSources .add (data );
223
+ if (ELSE_NESTED_KEYWORD .equals (source )) {
224
+ elseNested = true ;
225
+ }
226
+
227
+ if (ELSE_KEYWORD .equals (source ) || ELSE_FLATTENED_KEYWORD .equals (source ) || elseNested ) {
228
+ if (elseSources .isEmpty ()) {
229
+ elseSources .add (data );
230
+ }
231
+ else {
232
+ LOG .warn ("Only one of '_else', '_elseFlattened' and '_elseNested' is allowed. Ignoring the superflous ones." );
233
+ }
220
234
} else {
221
235
dataRegistry .register (source , data );
222
236
}
@@ -238,12 +252,11 @@ public void startRecord(final String identifier) {
238
252
final String identifierFinal = identifier ;
239
253
240
254
outputStreamReceiver .startRecord (identifierFinal );
241
- dispatch (StandardEventNames .ID , identifierFinal , null );
255
+ dispatch (StandardEventNames .ID , identifierFinal , null , false );
242
256
}
243
257
244
258
@ Override
245
259
public void endRecord () {
246
-
247
260
for (final FlushListener listener : recordEndListener ){
248
261
listener .flush (recordCount , currentEntityCount );
249
262
}
@@ -268,24 +281,20 @@ public void startEntity(final String name) {
268
281
entityCountStack .push (Integer .valueOf (entityCount ));
269
282
270
283
flattener .startEntity (name );
271
-
272
-
273
-
274
284
}
275
285
276
286
@ Override
277
287
public void endEntity () {
278
- dispatch (flattener .getCurrentPath (), "" , null );
288
+ dispatch (flattener .getCurrentPath (), "" , getElseSources (), true );
279
289
currentEntityCount = entityCountStack .pop ().intValue ();
280
290
flattener .endEntity ();
281
-
282
291
}
283
292
284
293
285
294
@ Override
286
295
public void literal (final String name , final String value ) {
296
+ currentLiteralName = name ;
287
297
flattener .literal (name , value );
288
-
289
298
}
290
299
291
300
@ Override
@@ -306,25 +315,48 @@ public void closeStream() {
306
315
outputStreamReceiver .closeStream ();
307
316
}
308
317
309
- protected void dispatch (final String path , final String value , final List <NamedValueReceiver > fallback ) {
310
- final List <NamedValueReceiver > matchingData = findMatchingData (path , fallback );
311
- if (null != matchingData ) {
318
+ private void dispatch (final String path , final String value , final List <NamedValueReceiver > fallbackReceiver , final boolean endEntity ) {
319
+ final List <NamedValueReceiver > matchingData = getData (path );
320
+
321
+ if (matchingData != null ) {
312
322
send (path , value , matchingData );
313
323
}
324
+ else if (fallbackReceiver != null ) {
325
+ if (endEntity ) {
326
+ if (elseNestedEntityStarted ) {
327
+ outputStreamReceiver .endEntity ();
328
+ elseNestedEntityStarted = false ;
329
+ }
330
+ }
331
+ else {
332
+ final String entityName = elseNested ? flattener .getCurrentEntityName () : null ;
333
+
334
+ if (entityName != null ) {
335
+ if (getData (entityName ) == null ) {
336
+ if (!elseNestedEntityStarted ) {
337
+ outputStreamReceiver .startEntity (entityName );
338
+ elseNestedEntityStarted = true ;
339
+ }
340
+
341
+ send (currentLiteralName , value , fallbackReceiver );
342
+ }
343
+ }
344
+ else {
345
+ send (path , value , fallbackReceiver );
346
+ }
347
+ }
348
+ }
314
349
}
315
350
316
- private List <NamedValueReceiver > findMatchingData (final String path , final List < NamedValueReceiver > fallback ) {
351
+ private List <NamedValueReceiver > getData (final String path ) {
317
352
final List <NamedValueReceiver > matchingData = dataRegistry .get (path );
318
- if (matchingData == null || matchingData .isEmpty ()) {
319
- return fallback ;
320
- }
321
- return matchingData ;
353
+ return matchingData != null && !matchingData .isEmpty () ? matchingData : null ;
322
354
}
323
355
324
- private void send (final String key , final String value , final List <NamedValueReceiver > dataList ) {
356
+ private void send (final String path , final String value , final List <NamedValueReceiver > dataList ) {
325
357
for (final NamedValueReceiver data : dataList ) {
326
358
try {
327
- data .receive (key , value , null , recordCount , currentEntityCount );
359
+ data .receive (path , value , null , recordCount , currentEntityCount );
328
360
} catch (final RuntimeException e ) {
329
361
errorHandler .error (e );
330
362
}
@@ -357,7 +389,7 @@ public void receive(final String name, final String value, final NamedValueSourc
357
389
}
358
390
359
391
if (name .length () != 0 && name .charAt (0 ) == FEEDBACK_CHAR ) {
360
- dispatch (name , value , null );
392
+ dispatch (name , value , null , false );
361
393
return ;
362
394
}
363
395
0 commit comments