Skip to content

Commit c337ce9

Browse files
committed
Add module to turn records into entities
The `RecordToEntity` module replaces start-record and end-record events with start- and end-entity events. This functionality is similar to the behaviour of the `RecordBoundaryRemover` when created with an entity name. However, the new module is more flexible as the entity name is specified using a setter and the output of the id literal is also configurable. Therefore, the single argument constructor in `RecordBoundaryRemover` is marked as deprecated with the intention of removing it in a future release.
1 parent a5e811d commit c337ce9

File tree

3 files changed

+240
-17
lines changed

3 files changed

+240
-17
lines changed

src/main/java/org/culturegraph/mf/stream/pipe/RecordBounderyRemover.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
/*
2-
* Copyright 2013, 2014 Deutsche Nationalbibliothek
2+
* Copyright 2016 Deutsche Nationalbibliothek
33
*
4-
* Licensed under the Apache License, Version 2.0 the "License";
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
99
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
1515
*/
1616
package org.culturegraph.mf.stream.pipe;
1717

@@ -25,29 +25,38 @@
2525

2626
/**
2727
* Removes record boundaries
28-
*
28+
*
2929
* @author Markus Michael Geipel
3030
*
3131
*/
3232
@Description("Removes record boundaries")
3333
@In(StreamReceiver.class)
3434
@Out(StreamReceiver.class)
35-
public final class RecordBounderyRemover
35+
public final class RecordBounderyRemover
3636
extends DefaultStreamPipe<StreamReceiver> {
37-
37+
3838
private final String entityName;
39-
39+
40+
/**
41+
* Creates an instance of RecordBounderyRemover that replaces the record
42+
* events with entity events.
43+
*
44+
* @param entityName name of the generated entity.
45+
* @deprecated Use {@link RecordToEntity} instead. This constructor will be
46+
* removed in release 4.0.0.
47+
*/
48+
@Deprecated
4049
public RecordBounderyRemover(final String entityName) {
4150
super();
4251
this.entityName = entityName;
4352
}
44-
53+
4554
public RecordBounderyRemover(){
4655
super();
4756
this.entityName = null;
48-
57+
4958
}
50-
59+
5160
@Override
5261
public void startRecord(final String identifier) {
5362
assert !isClosed();
@@ -84,4 +93,5 @@ public void literal(final String name, final String value) {
8493
assert !isClosed();
8594
getReceiver().literal(name, value);
8695
}
96+
8797
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2016 Deutsche Nationalbibliothek
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.culturegraph.mf.stream.pipe;
18+
19+
import org.culturegraph.mf.framework.DefaultStreamPipe;
20+
import org.culturegraph.mf.framework.StreamReceiver;
21+
22+
/**
23+
* Turns a record into an entity that can be embedded into another record.
24+
*
25+
* <p>The module captures the <i>start-record</i> and <i>end-record</i> events
26+
* and replaces them with <i>start-entity</i> and <i>end-entity</i> events. All
27+
* other events are forwarded unchanged. The name of the generated entity can be
28+
* set with {@link #setEntityName(String)}.
29+
*
30+
* <p>Optionally, the record identifier can be added to the generated entity.
31+
* This is configured with {@link #setIdLiteralName(String)}.
32+
*
33+
* @author Christoph Böhme
34+
* @see RecordBounderyRemover
35+
*/
36+
public class RecordToEntity extends DefaultStreamPipe<StreamReceiver> {
37+
38+
/**
39+
* Default value for the name of the entity that replaces the record.
40+
*/
41+
public static final String DEFAULT_ENTITY_NAME = "record";
42+
43+
private String entityName = DEFAULT_ENTITY_NAME;
44+
private String idLiteralName;
45+
46+
public String getEntityName() {
47+
return entityName;
48+
}
49+
50+
/**
51+
* Sets the name of the entity which replaces the record. The default name is
52+
* &quot;{@value DEFAULT_ENTITY_NAME}&quot;.
53+
*
54+
* <p>The entity name may be changed while processing an event stream. It
55+
* becomes effective with the next record.
56+
*
57+
* @param entityName the new name for generated entities. Can be empty which
58+
* results in unnamed entities being emitted. Must not be
59+
* null.
60+
*/
61+
public void setEntityName(final String entityName) {
62+
this.entityName = entityName;
63+
}
64+
65+
/**
66+
* Returns the name of the literal that contains the record id if enabled.
67+
*
68+
* @return the name of the id literal. If output of id literals is disabled
69+
* then null is returned.
70+
*/
71+
public String getIdLiteralName() {
72+
return idLiteralName;
73+
}
74+
75+
/**
76+
* Enables output of a literal with the record identifier of the converted
77+
* record. The literal is emitted directly after the start-entity event for
78+
* the record before any other events are generated.
79+
*
80+
* <p>By default no id literal is generated.
81+
*
82+
* <p>The id literal may be changed while processing an event stream. The
83+
* change becomes effective with the next record.
84+
*
85+
* @param name the name of the record-id literal
86+
*/
87+
public void setIdLiteralName(final String name) {
88+
idLiteralName = name;
89+
}
90+
91+
@Override
92+
public void startRecord(final String identifier) {
93+
getReceiver().startEntity(entityName);
94+
if (idLiteralName != null) {
95+
getReceiver().literal(idLiteralName, identifier);
96+
}
97+
}
98+
99+
@Override
100+
public void endRecord() {
101+
getReceiver().endEntity();
102+
}
103+
104+
@Override
105+
public void startEntity(final String name) {
106+
getReceiver().startEntity(name);
107+
}
108+
109+
@Override
110+
public void endEntity() {
111+
getReceiver().endEntity();
112+
}
113+
114+
@Override
115+
public void literal(final String name, final String value) {
116+
getReceiver().literal(name, value);
117+
}
118+
119+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2016 Deutsche Nationalbibliothek
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.culturegraph.mf.stream.pipe;
18+
19+
import static org.mockito.Mockito.inOrder;
20+
import static org.mockito.Mockito.times;
21+
22+
import org.culturegraph.mf.framework.StreamReceiver;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
import org.mockito.InOrder;
26+
import org.mockito.Mock;
27+
import org.mockito.MockitoAnnotations;
28+
29+
/**
30+
* Tests for class {@link RecordToEntity}.
31+
*
32+
* @author Christoph Böhme
33+
*/
34+
public class RecordToEntityTest {
35+
36+
@Mock
37+
private StreamReceiver receiver;
38+
39+
private RecordToEntity recordToEntity;
40+
41+
@Before
42+
public void init() {
43+
MockitoAnnotations.initMocks(this);
44+
recordToEntity = new RecordToEntity();
45+
recordToEntity.setReceiver(receiver);
46+
}
47+
48+
@Test
49+
public void shouldReplaceRecordEventsWithEntityEvents() {
50+
recordToEntity.startRecord("1");
51+
recordToEntity.literal("literal", "value");
52+
recordToEntity.startEntity("entity");
53+
recordToEntity.endEntity();
54+
recordToEntity.endRecord();
55+
recordToEntity.closeStream();
56+
57+
InOrder ordered = inOrder(receiver);
58+
ordered.verify(receiver)
59+
.startEntity(RecordToEntity.DEFAULT_ENTITY_NAME);
60+
ordered.verify(receiver).literal("literal", "value");
61+
ordered.verify(receiver).startEntity("entity");
62+
ordered.verify(receiver, times(2)).endEntity();
63+
ordered.verify(receiver).closeStream();
64+
}
65+
66+
@Test
67+
public void setEntityName_shouldChangeNameOfGeneratedEntity() {
68+
recordToEntity.setEntityName("container");
69+
70+
recordToEntity.startRecord("1");
71+
recordToEntity.endRecord();
72+
recordToEntity.closeStream();
73+
74+
InOrder ordered = inOrder(receiver);
75+
ordered.verify(receiver).startEntity("container");
76+
ordered.verify(receiver).endEntity();
77+
ordered.verify(receiver).closeStream();
78+
}
79+
80+
@Test
81+
public void setIdLiteralName_shouldEnableOutputOfRecordIdAsLiteral() {
82+
recordToEntity.setIdLiteralName("record-id");
83+
84+
recordToEntity.startRecord("1");
85+
receiver.endRecord();
86+
receiver.closeStream();
87+
88+
InOrder ordered = inOrder(receiver);
89+
ordered.verify(receiver)
90+
.startEntity(RecordToEntity.DEFAULT_ENTITY_NAME);
91+
ordered.verify(receiver).literal("record-id", "1");
92+
}
93+
94+
}

0 commit comments

Comments
 (0)