Skip to content

Commit f1c2470

Browse files
committed
Added support for conditional activation of collectors.
This commits introduces an <if> statement which can be used to control under which conditions a collector generates output. It can be used for example to write a combine statement that only generates outputif data3 has a value of "x": <combine name="output" value="${a}${b}"> <if> <data source="data3"> <equals string="x" /> </data> </if> <data source="data1" name="a" /> <data source="data2" name="b" /> </combine> The quantors introduced by commits 475a55f, 12a0537 and e65f6d2 are meant to be used inside the <if> statement.
1 parent 7d1835b commit f1c2470

File tree

9 files changed

+304
-44
lines changed

9 files changed

+304
-44
lines changed

src/main/java/org/culturegraph/mf/morph/AbstractMetamorphDomWalker.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ public static enum MMTAG {
5353
* XML attributes
5454
*/
5555
public static enum ATTRITBUTE {
56-
VERSION("version"),
57-
SOURCE("source"),
58-
VALUE("value"),
56+
VERSION("version"),
57+
SOURCE("source"),
58+
VALUE("value"),
5959
NAME("name"),
60-
CLASS("class"),
61-
DEFAULT("default"),
62-
ENTITY_MARKER("entityMarker"),
60+
CLASS("class"),
61+
DEFAULT("default"),
62+
ENTITY_MARKER("entityMarker"),
6363
FLUSH_WITH("flushWith");
6464

6565
private final String string;
@@ -76,6 +76,7 @@ public String getString() {
7676
private static final String DATA = "data";
7777
private static final String MAP = "map";
7878
private static final String MACRO = "call-macro";
79+
private static final String IF = "if";
7980
private static final String POSTPROCESS = "postprocess";
8081
private static final String ENTITY_NAME = "entity-name";
8182
private static final String SCHEMA_FILE = "schemata/metamorph.xsd";
@@ -105,7 +106,7 @@ protected final MapFactory getMapFactory() {
105106
public final void walk(final String morphDef) {
106107
try {
107108
walk(ResourceUtil.getStream(morphDef));
108-
} catch (FileNotFoundException e) {
109+
} catch (final FileNotFoundException e) {
109110
throw new MorphDefException(e);
110111
}
111112
}
@@ -270,18 +271,26 @@ private void handleMacros(final Node node) {
270271

271272
protected abstract void exitCollect(Node node);
272273

273-
protected abstract void enterName(Node node);
274+
protected abstract void enterName(Node node);
274275

275276
protected abstract void exitName(Node node);
276277

278+
protected abstract void enterIf(Node node);
279+
280+
protected abstract void exitIf(Node node);
281+
277282
protected abstract void handleFunction(Node functionNode);
278283

279284
private void handleRule(final Node node) {
280285
final String nodeName = node.getLocalName();
281286
if (getCollectFactory().containsKey(nodeName)) {
282287
enterCollect(node);
283288
for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
284-
if (POSTPROCESS.equals(child.getLocalName())) {
289+
if (IF.equals(child.getLocalName())) {
290+
enterIf(child);
291+
handleRule(child.getFirstChild());
292+
exitIf(child);
293+
} else if (POSTPROCESS.equals(child.getLocalName())) {
285294
handlePostprocess(child);
286295
} else if (ENTITY_NAME.equals(child.getLocalName())) {
287296
enterName(child);
@@ -311,6 +320,10 @@ private void handleRule(final Node node) {
311320
}
312321
}
313322

323+
private void handleIf(final Node node) {
324+
325+
}
326+
314327
private void handlePostprocess(final Node node) {
315328
for (Node functionNode = node.getFirstChild(); functionNode != null; functionNode = functionNode
316329
.getNextSibling()) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2013 Christoph Böhme
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+
package org.culturegraph.mf.morph;
17+
18+
/**
19+
* Interface for statements that can be made conditional.
20+
*
21+
* @author Christoph Böhme
22+
*
23+
*/
24+
public interface ConditionAware {
25+
26+
void setConditionSource(NamedValueSource receiver);
27+
28+
}

src/main/java/org/culturegraph/mf/morph/MorphBuilder.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public final class MorphBuilder extends AbstractMetamorphDomWalker {
4747
private final Deque<Collect> collectStack;
4848
private Data data;
4949
private boolean setEntityName;
50-
50+
private boolean setCondition;
51+
5152
protected MorphBuilder(final Metamorph metamorph) {
5253
super();
5354
this.collectStack = new LinkedList<Collect>();
@@ -107,7 +108,7 @@ protected void handleFunctionDefinition(final Node functionDefNode) {
107108
final String className = resolvedAttribute(functionDefNode, ATTRITBUTE.CLASS);
108109
try {
109110
clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
110-
} catch (ClassNotFoundException e) {
111+
} catch (final ClassNotFoundException e) {
111112
throw new MorphDefException("Function " + className + NOT_FOUND, e);
112113
}
113114
if (Function.class.isAssignableFrom(clazz)) {
@@ -144,6 +145,11 @@ protected void enterData(final Node dataNode) {
144145
((Entity) collectStack.peek()).setNameSource(data);
145146
setEntityName = false;
146147
}
148+
149+
if (setCondition) {
150+
collectStack.peek().setConditionSource(data);
151+
setCondition = false;
152+
}
147153
}
148154

149155
@Override
@@ -168,6 +174,16 @@ protected void exitName(final Node nameNode) {
168174
setEntityName = false;
169175
}
170176

177+
@Override
178+
protected void enterIf(final Node nameNode) {
179+
setCondition = true;
180+
}
181+
182+
@Override
183+
protected void exitIf(final Node nameNode) {
184+
setCondition = false;
185+
}
186+
171187
@Override
172188
protected void enterCollect(final Node node) {
173189
final Map<String, String> attributes = resolvedAttributeMap(node);
@@ -183,6 +199,11 @@ protected void enterCollect(final Node node) {
183199
((Entity) collectStack.peek()).setNameSource(collect);
184200
setEntityName = false;
185201
}
202+
203+
if (setCondition) {
204+
collectStack.peek().setConditionSource(collect);
205+
setCondition = false;
206+
}
186207

187208
collectStack.push(collect);
188209
}
@@ -204,10 +225,10 @@ protected void exitCollect(final Node node) {
204225
registerFlush(flushWith, collect);
205226
}
206227
}
207-
228+
208229
private void registerFlush(final String flushWith, final FlushListener flushListener) {
209230
final String[] keysSplit = OR_PATTERN.split(flushWith);
210-
for (String key : keysSplit) {
231+
for (final String key : keysSplit) {
211232
if (key.equals(RECORD)) {
212233
metamorph.registerRecordEndFlush(flushListener);
213234
} else {

src/main/java/org/culturegraph/mf/morph/MorphVisualizer.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ private static String buildRecord(final String identifier, final String name, fi
7878
builder.append("<TR><TD COLSPAN=\"2\" BGCOLOR=\"" + color + "\"><B>" + name + "</B></TD></TR>");
7979
}
8080

81-
for (Entry<String, String> entry : attributes.entrySet()) {
81+
for (final Entry<String, String> entry : attributes.entrySet()) {
8282
builder.append("<TR><TD>" + StringEscapeUtils.escapeXml(entry.getKey()) + "</TD><TD>'" + StringEscapeUtils.escapeXml(entry.getValue())
8383
+ "'</TD></TR>");
8484
}
@@ -94,7 +94,7 @@ private static String buildMap(final String identifier, final String name, final
9494
builder.append("<TR><TD COLSPAN=\"2\"><B>" + name + "</B></TD></TR>");
9595
}
9696

97-
for (Entry<String, String> entry : attributes.entrySet()) {
97+
for (final Entry<String, String> entry : attributes.entrySet()) {
9898
builder.append("<TR><TD>" + StringEscapeUtils.escapeXml(entry.getKey()) + "</TD><TD>'" + StringEscapeUtils.escapeXml(entry.getValue())
9999
+ "'</TD></TR>");
100100
}
@@ -122,7 +122,7 @@ private void addIncludeEdge(final String fromId, final String toId) {
122122
@Override
123123
protected void finish() {
124124

125-
for (String source : sources) {
125+
for (final String source : sources) {
126126
final String color;
127127
if (source.startsWith(RECURSION_INDICATOR)) {
128128
color = "lemonchiffon";
@@ -237,8 +237,7 @@ protected void enterName(final Node node) {
237237

238238
@Override
239239
protected void exitName(final Node node) {
240-
// TODO Auto-generated method stub
241-
240+
// Nothing to do
242241
}
243242

244243
private void exit(final Node node) {
@@ -300,4 +299,14 @@ private void incrementChildCount() {
300299
childCountStack.push(Integer.valueOf(1 + childCountStack.pop().intValue()));
301300
}
302301

302+
@Override
303+
protected void enterIf(final Node node) {
304+
((Element)node.getFirstChild()).setAttribute(ATTRITBUTE.NAME.getString(), "<if>");
305+
}
306+
307+
@Override
308+
protected void exitIf(final Node node) {
309+
// Nothing to do
310+
}
311+
303312
}

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

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
* Common basis for {@link Entity}, {@link Combine} etc.
2424
*
2525
* @author Markus Michael Geipel
26-
26+
* @author Christoph Böhme
27+
*
2728
*/
2829
public abstract class AbstractCollect extends AbstractNamedValuePipeHead implements Collect {
2930

@@ -35,7 +36,10 @@ public abstract class AbstractCollect extends AbstractNamedValuePipeHead impleme
3536
private String value;
3637
private final Metamorph metamorph;
3738
private boolean waitForFlush;
38-
39+
private boolean conditionMet;
40+
41+
private NamedValueSource conditionSource;
42+
3943
public AbstractCollect(final Metamorph metamorph) {
4044
super();
4145
this.metamorph = metamorph;
@@ -53,6 +57,14 @@ protected final int getEntityCount() {
5357
return oldEntity;
5458
}
5559

60+
protected final boolean isConditionMet() {
61+
return conditionMet;
62+
}
63+
64+
protected final void setConditionMet(final boolean conditionMet) {
65+
this.conditionMet = conditionMet;
66+
}
67+
5668
@Override
5769
public final void setWaitForFlush(final boolean waitForFlush) {
5870
this.waitForFlush = waitForFlush;
@@ -83,6 +95,12 @@ public final void setName(final String name) {
8395
this.name = name;
8496
}
8597

98+
@Override
99+
public final void setConditionSource(final NamedValueSource conditionSource) {
100+
this.conditionSource = conditionSource;
101+
this.conditionMet = conditionSource == null;
102+
}
103+
86104
public final String getValue() {
87105
return value;
88106
}
@@ -97,6 +115,7 @@ public final void setValue(final String value) {
97115

98116
protected final void updateCounts(final int currentRecord, final int currentEntity) {
99117
if (!isSameRecord(currentRecord)) {
118+
conditionMet = conditionSource == null;
100119
clear();
101120
oldRecord = currentRecord;
102121
}
@@ -117,25 +136,28 @@ protected final boolean isSameRecord(final int currentRecord) {
117136
@Override
118137
public final void receive(final String name, final String value, final NamedValueSource source,
119138
final int recordCount, final int entityCount) {
120-
updateCounts(recordCount, entityCount);
121-
122-
// if(FLUSH.equals(name)){
123-
// flush(name, recordCount, entityCount);
124-
// }
125-
126-
receive(name, value, source);
127-
128-
if (!waitForFlush && isComplete()) {
129-
emit();
130-
if (resetAfterEmit) {
131-
clear();
132-
}
133-
}
134-
}
139+
140+
updateCounts(recordCount, entityCount);
141+
142+
if (source == conditionSource) {
143+
conditionMet = true;
144+
} else {
145+
receive(name, value, source);
146+
}
147+
148+
if (!waitForFlush && isConditionMet() && isComplete()) {
149+
emit();
150+
if (resetAfterEmit) {
151+
clear();
152+
}
153+
}
154+
}
135155

136156
@Override
137157
public final void addNamedValueSource(final NamedValueSource namedValueSource) {
138-
onNamedValueSourceAdded(namedValueSource);
158+
if (namedValueSource != conditionSource) {
159+
onNamedValueSourceAdded(namedValueSource);
160+
}
139161
}
140162

141163
protected void onNamedValueSourceAdded(final NamedValueSource namedValueSource) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
* Common basis for {@link Entity}, {@link Combine} etc.
2222
*
2323
* @author Markus Michael Geipel
24-
24+
* @author Christoph Böhme
25+
*
2526
*/
2627
public abstract class AbstractFlushingCollect extends AbstractCollect {
2728

@@ -34,7 +35,7 @@ public AbstractFlushingCollect(final Metamorph metamorph) {
3435

3536
@Override
3637
public final void flush(final int recordCount, final int entityCount) {
37-
if (isSameRecord(recordCount) && sameEntityConstraintSatisfied(entityCount)) {
38+
if (isSameRecord(recordCount) && sameEntityConstraintSatisfied(entityCount) && isConditionMet()) {
3839
emit();
3940
if (getReset()) {
4041
clear();

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.culturegraph.mf.morph.collectors;
1717

18+
import org.culturegraph.mf.morph.ConditionAware;
1819
import org.culturegraph.mf.morph.FlushListener;
1920
import org.culturegraph.mf.morph.Metamorph;
2021
import org.culturegraph.mf.morph.NamedValuePipeHead;
@@ -26,7 +27,7 @@
2627
* @author Markus Michael Geipel
2728
*
2829
*/
29-
public interface Collect extends FlushListener, NamedValuePipeHead{
30+
public interface Collect extends FlushListener, ConditionAware, NamedValuePipeHead{
3031

3132
void setWaitForFlush(final boolean waitForFlush);
3233
void setSameEntity(boolean sameEntity);
@@ -36,6 +37,4 @@ public interface Collect extends FlushListener, NamedValuePipeHead{
3637
String getName();
3738
void setName(String name);
3839

39-
40-
4140
}

0 commit comments

Comments
 (0)