Skip to content

Commit bec6763

Browse files
authored
Merge pull request #238 from metafacture/addDebugRecordFunction
Add `print_record()` Fix function.
2 parents 49d88da + 69482cf commit bec6763

File tree

8 files changed

+298
-5
lines changed

8 files changed

+298
-5
lines changed

README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,36 @@ paste("my.string", "~Hi", "a", "~how are you?")
305305
# "my.string": "Hi eeny how are you?"
306306
```
307307

308+
##### `print_record`
309+
310+
Prints the current record as JSON either to standard output or to a file.
311+
312+
Parameters:
313+
314+
- `prefix` (optional): Prefix to print before the record; may include [format directives](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#syntax) for counter and record ID (in that order). (Default: Empty string)
315+
316+
Options:
317+
318+
- `compression` (file output only): Compression mode. (Default: `auto`)
319+
- `destination`: Destination to write the record to; may include [format directives](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#syntax) for counter and record ID (in that order). (Default: `stdout`)
320+
- `encoding` (file output only): Encoding used by the underlying writer. (Default: `UTF-8`)
321+
- `footer`: Footer which is output after the record. (Default: `\n`)
322+
- `header`: Header which is output before the record. (Default: Empty string)
323+
- `id`: Field name which contains the record ID; if found, will be available for inclusion in `prefix` and `destination`. (Default: `_id`)
324+
- `pretty`: Whether to use pretty printing. (Default: `false`)
325+
326+
```perl
327+
print_record(["<prefix>"][, <options>...])
328+
```
329+
330+
E.g.:
331+
332+
```perl
333+
print_record("%d) Before transformation: ")
334+
print_record(destination: "record-%2$s.json", id: "001", pretty: "true")
335+
print_record(destination: "record-%03d.json.gz", header: "After transformation: ")
336+
```
337+
308338
##### `random`
309339

310340
Creates (or replaces) a field with a random number (less than the specified maximum).
@@ -369,8 +399,8 @@ Creates (or replaces) a field with the current timestamp.
369399

370400
Options:
371401

372-
- `format`: Date and time pattern as in [java.text.SimpleDateFormat](https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html). (Default: Unix timestamp)
373-
- `timezone`: Time zone as in [java.util.TimeZone](https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html). (Default: UTC)
402+
- `format`: Date and time pattern as in [java.text.SimpleDateFormat](https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html). (Default: `timestamp`)
403+
- `timezone`: Time zone as in [java.util.TimeZone](https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html). (Default: `UTC`)
374404
- `language`: Language tag as in [java.util.Locale](https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html). (Default: The locale of the host system)
375405

376406
```perl

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ subprojects {
3434
versions = [
3535
'ace': '1.3.3',
3636
'equalsverifier': '3.8.2',
37+
'jackson': '2.13.3',
3738
'jetty': '9.4.14.v20181114',
3839
'jquery': '3.3.1-1',
3940
'junit_jupiter': '5.8.2',

metafix/build.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def passSystemProperties = {
1212
dependencies {
1313
implementation "org.eclipse.xtext:org.eclipse.xtext:${versions.xtext}"
1414
implementation "org.eclipse.xtext:org.eclipse.xtext.xbase:${versions.xtext}"
15+
implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
1516
implementation "com.google.guava:guava:${versions.guava}"
1617
implementation "org.slf4j:slf4j-api:${versions.slf4j}"
1718

@@ -25,9 +26,11 @@ dependencies {
2526
runtimeOnly "org.slf4j:slf4j-simple:${versions.slf4j}"
2627

2728
implementation "org.metafacture:metafacture-commons:${versions.metafacture}"
28-
implementation "org.metafacture:metafacture-mangling:${versions.metafacture}"
29-
implementation "org.metafacture:metafacture-javaintegration:${versions.metafacture}"
3029
implementation "org.metafacture:metafacture-flowcontrol:${versions.metafacture}"
30+
implementation "org.metafacture:metafacture-framework:${versions.metafacture}"
31+
implementation "org.metafacture:metafacture-io:${versions.metafacture}"
32+
implementation "org.metafacture:metafacture-javaintegration:${versions.metafacture}"
33+
implementation "org.metafacture:metafacture-mangling:${versions.metafacture}"
3134
implementation "org.metafacture:metamorph:${versions.metafacture}"
3235

3336
testImplementation "nl.jqno.equalsverifier:equalsverifier:${versions.equalsverifier}"

metafix/src/main/java/org/metafacture/metafix/FixMethod.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,24 @@
1616

1717
package org.metafacture.metafix;
1818

19+
import org.metafacture.framework.StandardEventNames;
20+
import org.metafacture.io.ObjectWriter;
1921
import org.metafacture.metafix.api.FixFunction;
2022
import org.metafacture.metamorph.api.Maps;
2123
import org.metafacture.metamorph.functions.ISBN;
2224
import org.metafacture.metamorph.functions.Timestamp;
2325
import org.metafacture.metamorph.maps.FileMap;
2426

2527
import java.io.File;
28+
import java.io.IOException;
2629
import java.util.Arrays;
2730
import java.util.Collections;
2831
import java.util.Comparator;
32+
import java.util.HashMap;
2933
import java.util.List;
3034
import java.util.Map;
3135
import java.util.Random;
36+
import java.util.concurrent.atomic.LongAdder;
3237
import java.util.function.Function;
3338
import java.util.function.Predicate;
3439
import java.util.function.UnaryOperator;
@@ -208,6 +213,38 @@ private boolean literalString(final String s) {
208213
return s.startsWith("~");
209214
}
210215
},
216+
print_record {
217+
private final Map<Metafix, LongAdder> scopedCounter = new HashMap<>();
218+
219+
@Override
220+
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {
221+
final String destination = options.getOrDefault("destination", ObjectWriter.STDOUT);
222+
final Value idValue = record.get(options.getOrDefault("id", StandardEventNames.ID));
223+
224+
final boolean pretty = getBoolean(options, "pretty");
225+
226+
final LongAdder counter = scopedCounter.computeIfAbsent(metafix, k -> new LongAdder());
227+
counter.increment();
228+
229+
final String id = Value.isNull(idValue) ? "" : idValue.toString();
230+
final String prefix = params.isEmpty() ? "" : String.format(params.get(0), counter.sum(), id);
231+
final ObjectWriter<String> writer = new ObjectWriter<>(String.format(destination, counter.sum(), id));
232+
233+
withOption(options, "compression", writer::setCompression);
234+
withOption(options, "encoding", writer::setEncoding);
235+
withOption(options, "footer", writer::setFooter);
236+
withOption(options, "header", writer::setHeader);
237+
238+
try {
239+
writer.process(prefix + record.toJson(pretty));
240+
}
241+
catch (final IOException e) {
242+
// Log a warning? Print string representation instead?
243+
}
244+
245+
writer.closeStream();
246+
}
247+
},
211248
random {
212249
@Override
213250
public void apply(final Metafix metafix, final Record record, final List<String> params, final Map<String, String> options) {

metafix/src/main/java/org/metafacture/metafix/Record.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
import org.metafacture.metafix.FixPath.InsertMode;
2020
import org.metafacture.metafix.Value.TypeMatcher;
2121

22+
import com.fasterxml.jackson.core.JsonFactory;
23+
import com.fasterxml.jackson.core.JsonGenerator;
24+
import com.fasterxml.jackson.core.SerializableString;
25+
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
26+
27+
import java.io.IOException;
28+
import java.io.StringWriter;
29+
import java.io.UncheckedIOException;
2230
import java.util.Collection;
2331
import java.util.Deque;
2432
import java.util.LinkedHashMap;
@@ -110,6 +118,27 @@ public String toString() {
110118
return super.toString();
111119
}
112120

121+
public String toJson() throws IOException {
122+
return toJson(false);
123+
}
124+
125+
public String toJson(final boolean prettyPrinting) throws IOException {
126+
final StringWriter writer = new StringWriter();
127+
final JsonGenerator jsonGenerator = new JsonFactory().createGenerator(writer);
128+
jsonGenerator.setPrettyPrinter(prettyPrinting ? new DefaultPrettyPrinter((SerializableString) null) : null);
129+
130+
try {
131+
toJson(jsonGenerator);
132+
}
133+
catch (final UncheckedIOException e) {
134+
throw e.getCause();
135+
}
136+
137+
jsonGenerator.flush();
138+
139+
return writer.toString();
140+
}
141+
113142
/**
114143
* Retrieves the field value from this record. Falls back to retrieving the
115144
* <i>virtual</i> field if the field name is not already

metafix/src/main/java/org/metafacture/metafix/Value.java

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import org.metafacture.commons.tries.SimpleRegexTrie;
2020
import org.metafacture.commons.tries.WildcardTrie;
2121

22+
import com.fasterxml.jackson.core.JsonGenerator;
23+
24+
import java.io.IOException;
25+
import java.io.UncheckedIOException;
2226
import java.util.ArrayList;
2327
import java.util.Collection;
2428
import java.util.ConcurrentModificationException;
@@ -44,7 +48,7 @@
4448
* Represents a record value, i.e., either an {@link Array}, a {@link Hash},
4549
* or a {@link String}.
4650
*/
47-
public class Value {
51+
public class Value { // checkstyle-disable-line ClassDataAbstractionCoupling
4852

4953
private static final String FIELD_PATH_SEPARATOR = "\\.";
5054

@@ -244,6 +248,31 @@ public String toString() {
244248
);
245249
}
246250

251+
private void toJson(final JsonGenerator jsonGenerator) {
252+
if (isNull()) {
253+
try {
254+
jsonGenerator.writeNull();
255+
}
256+
catch (final IOException e) {
257+
throw new UncheckedIOException(e);
258+
}
259+
}
260+
else {
261+
matchType()
262+
.ifArray(a -> a.toJson(jsonGenerator))
263+
.ifHash(h -> h.toJson(jsonGenerator))
264+
.ifString(s -> {
265+
try {
266+
jsonGenerator.writeString(s);
267+
}
268+
catch (final IOException e) {
269+
throw new UncheckedIOException(e);
270+
}
271+
})
272+
.orElseThrow();
273+
}
274+
}
275+
247276
/*package-private*/ static String[] split(final String fieldPath) {
248277
return fieldPath.split(FIELD_PATH_SEPARATOR);
249278
}
@@ -354,6 +383,8 @@ private abstract static class AbstractValueType {
354383
@Override
355384
public abstract String toString();
356385

386+
protected abstract void toJson(JsonGenerator jsonGenerator);
387+
357388
}
358389

359390
/**
@@ -427,6 +458,18 @@ public String toString() {
427458
return list.toString();
428459
}
429460

461+
@Override
462+
protected void toJson(final JsonGenerator jsonGenerator) {
463+
try {
464+
jsonGenerator.writeStartArray();
465+
forEach(v -> v.toJson(jsonGenerator));
466+
jsonGenerator.writeEndArray();
467+
}
468+
catch (final IOException e) {
469+
throw new UncheckedIOException(e);
470+
}
471+
}
472+
430473
public void remove(final int index) {
431474
list.remove(index);
432475
}
@@ -693,6 +736,29 @@ public String toString() {
693736
return map.toString();
694737
}
695738

739+
@Override
740+
protected void toJson(final JsonGenerator jsonGenerator) {
741+
try {
742+
jsonGenerator.writeStartObject();
743+
744+
forEach((f, v) -> {
745+
try {
746+
jsonGenerator.writeFieldName(f);
747+
}
748+
catch (final IOException e) {
749+
throw new UncheckedIOException(e);
750+
}
751+
752+
v.toJson(jsonGenerator);
753+
});
754+
755+
jsonGenerator.writeEndObject();
756+
}
757+
catch (final IOException e) {
758+
throw new UncheckedIOException(e);
759+
}
760+
}
761+
696762
/**
697763
* Avoids {@link ConcurrentModificationException} when modifying the hash based on matched fields.
698764
*

0 commit comments

Comments
 (0)