Skip to content

Commit 048c6ba

Browse files
committed
Added reverse concatenation to concat in Metamorph
Introduced a new attribute called reverse for the concat-collector in Metamorph which inverses the concatenation order if true. Instead of appended values at the end of the output string they will be prepended before the string.
1 parent 8f3caeb commit 048c6ba

File tree

3 files changed

+128
-51
lines changed

3 files changed

+128
-51
lines changed

src/main/java/org/culturegraph/mf/morph/collectors/Concat.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public final class Concat extends AbstractFlushingCollect {
3030
private String prefix = "";
3131
private String postfix = "";
3232
private String delimiter = "";
33-
33+
private boolean reverse = false;
34+
35+
private String currentDelimiter = "";
36+
3437
public Concat(final Metamorph metamorph) {
3538
super(metamorph);
3639
setNamedValueReceiver(metamorph);
@@ -48,31 +51,42 @@ public void setDelimiter(final String delimiter) {
4851
this.delimiter = delimiter;
4952
}
5053

54+
public void setReverse(final boolean reverse) {
55+
this.reverse = reverse;
56+
}
57+
5158
@Override
5259
protected void emit() {
53-
if(builder.length()!=0){
54-
final String concat = builder.substring(0, builder.length()-delimiter.length());
55-
getNamedValueReceiver().receive(getName(), prefix + concat + postfix, this, getRecordCount(), getEntityCount());
60+
if (builder.length() != 0) {
61+
final String value = prefix + builder.toString() + postfix;
62+
getNamedValueReceiver().receive(getName(), value, this,
63+
getRecordCount(), getEntityCount());
5664
}
5765
}
5866

59-
60-
6167
@Override
6268
protected boolean isComplete() {
6369
return false;
6470
}
6571

6672
@Override
67-
protected void receive(final String name, final String value, final NamedValueSource source) {
68-
builder.append(value);
69-
builder.append(delimiter);
70-
}
73+
protected void receive(final String name, final String value,
74+
final NamedValueSource source) {
7175

76+
if (reverse) {
77+
builder.insert(0, currentDelimiter);
78+
builder.insert(0, value);
79+
} else {
80+
builder.append(currentDelimiter);
81+
builder.append(value);
82+
}
83+
currentDelimiter = delimiter;
84+
}
7285

7386
@Override
7487
protected void clear() {
7588
builder.delete(0, builder.length());
89+
currentDelimiter = "";
7690
}
7791

7892
}

src/main/resources/schemata/metamorph.xsd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,12 @@
320320
<attribute name="delimiter" type="string" use="required" />
321321
<attribute name="prefix" type="string" use="optional" />
322322
<attribute name="postfix" type="string" use="optional" />
323+
<attribute name="reverse" type="boolean" use="optional" default="false">
324+
<annotation>
325+
<documentation>If true values are not appended at the end
326+
of the output string but prepended at its start.</documentation>
327+
</annotation>
328+
</attribute>
323329

324330
<attribute name="flushWith" type="string" use="optional"
325331
default="record" />

src/test/java/org/culturegraph/mf/morph/collectors/ConcatTest.xml

Lines changed: 98 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -91,46 +91,103 @@
9191
</result>
9292
</test-case>
9393

94-
<!-- <test-case name="concat data flush"> -->
95-
<!-- <input type="text/x-cg+xml"> -->
96-
<!-- <cgxml:cgxml version="1.0"> -->
97-
<!-- <cgxml:records> -->
98-
<!-- <cgxml:record id="1"> -->
99-
100-
<!-- <cgxml:literal name="d" value="1" /> -->
101-
102-
<!-- <cgxml:literal name="d" value="2" /> -->
103-
<!-- <cgxml:literal name="d" value="3" /> -->
104-
<!-- <cgxml:literal name="f" value="" /> -->
105-
<!-- <cgxml:literal name="d" value="4" /> -->
106-
<!-- <cgxml:literal name="f" value="" /> -->
107-
108-
<!-- </cgxml:record> -->
109-
<!-- </cgxml:records> -->
110-
<!-- </cgxml:cgxml> -->
111-
<!-- </input> -->
112-
113-
<!-- <transformation type="text/x-metamorph+xml"> -->
114-
<!-- <mm:metamorph version="1"> -->
115-
<!-- <mm:rules> -->
116-
<!-- <mm:concat delimiter="" name="c"> -->
117-
<!-- <mm:data source="d"/> -->
118-
<!-- <mm:data source="f" name="_flush"/> -->
119-
<!-- </mm:concat> -->
120-
<!-- </mm:rules> -->
121-
<!-- </mm:metamorph> -->
122-
<!-- </transformation> -->
123-
124-
<!-- <result type="text/x-cg+xml"> -->
125-
<!-- <cgxml:cgxml version="1.0"> -->
126-
<!-- <cgxml:records> -->
127-
<!-- <cgxml:record id="1"> -->
128-
<!-- <cgxml:literal name="c" value="123" /> -->
129-
<!-- <cgxml:literal name="c" value="4" /> -->
130-
<!-- </cgxml:record> -->
131-
<!-- </cgxml:records> -->
132-
<!-- </cgxml:cgxml> -->
133-
<!-- </result> -->
134-
<!-- </test-case> -->
94+
<test-case name="Do not ignore empty values">
95+
<input type="text/x-cg+xml">
96+
<cgxml:records>
97+
<cgxml:record id="1">
98+
<cgxml:literal name="litA" value="" />
99+
<cgxml:literal name="litB" value="a" />
100+
<cgxml:literal name="litA" value="b" />
101+
</cgxml:record>
102+
</cgxml:records>
103+
</input>
104+
105+
<transformation type="text/x-metamorph+xml">
106+
<mm:metamorph version="1">
107+
<mm:rules>
108+
<mm:concat name="concat" delimiter=", ">
109+
<mm:data source="litA" />
110+
<mm:data source="litB" />
111+
</mm:concat>
112+
</mm:rules>
113+
</mm:metamorph>
114+
</transformation>
115+
116+
<result type="text/x-cg+xml">
117+
<cgxml:cgxml version="1.0">
118+
<cgxml:records>
119+
<cgxml:record id="1">
120+
<cgxml:literal name="concat" value=", a, b" />
121+
</cgxml:record>
122+
</cgxml:records>
123+
</cgxml:cgxml>
124+
</result>
125+
</test-case>
126+
127+
<test-case name="Reverse concatenation if reverse is true">
128+
<input type="text/x-cg+xml">
129+
<cgxml:records>
130+
<cgxml:record id="1">
131+
<cgxml:literal name="litA" value="1" />
132+
<cgxml:literal name="litB" value="2" />
133+
<cgxml:literal name="litA" value="3" />
134+
</cgxml:record>
135+
</cgxml:records>
136+
</input>
137+
138+
<transformation type="text/x-metamorph+xml">
139+
<mm:metamorph version="1">
140+
<mm:rules>
141+
<mm:concat name="concat" delimiter=", " reverse="true">
142+
<mm:data source="litA" />
143+
<mm:data source="litB" />
144+
</mm:concat>
145+
</mm:rules>
146+
</mm:metamorph>
147+
</transformation>
148+
149+
<result type="text/x-cg+xml">
150+
<cgxml:cgxml version="1.0">
151+
<cgxml:records>
152+
<cgxml:record id="1">
153+
<cgxml:literal name="concat" value="3, 2, 1" />
154+
</cgxml:record>
155+
</cgxml:records>
156+
</cgxml:cgxml>
157+
</result>
158+
</test-case>
159+
160+
<test-case name="Prefix and postfix should work as normal if reverse is true">
161+
<input type="text/x-cg+xml">
162+
<cgxml:records>
163+
<cgxml:record id="1">
164+
<cgxml:literal name="litA" value="1" />
165+
<cgxml:literal name="litB" value="2" />
166+
<cgxml:literal name="litA" value="3" />
167+
</cgxml:record>
168+
</cgxml:records>
169+
</input>
170+
171+
<transformation type="text/x-metamorph+xml">
172+
<mm:metamorph version="1">
173+
<mm:rules>
174+
<mm:concat name="concat" delimiter=", " prefix="(" postfix=")" reverse="true">
175+
<mm:data source="litA" />
176+
<mm:data source="litB" />
177+
</mm:concat>
178+
</mm:rules>
179+
</mm:metamorph>
180+
</transformation>
181+
182+
<result type="text/x-cg+xml">
183+
<cgxml:cgxml version="1.0">
184+
<cgxml:records>
185+
<cgxml:record id="1">
186+
<cgxml:literal name="concat" value="(3, 2, 1)" />
187+
</cgxml:record>
188+
</cgxml:records>
189+
</cgxml:cgxml>
190+
</result>
191+
</test-case>
135192

136193
</metamorph-test>

0 commit comments

Comments
 (0)