Skip to content

Commit d5fbd94

Browse files
more precise schema compatibility check
1 parent 3e62b4a commit d5fbd94

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

src/main/java/org/radarcns/util/CsvAvroConverter.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.radarcns.util;
1818

19+
import com.fasterxml.jackson.databind.JsonMappingException;
1920
import com.fasterxml.jackson.databind.MappingIterator;
2021
import com.fasterxml.jackson.databind.ObjectReader;
2122
import com.fasterxml.jackson.databind.ObjectWriter;
@@ -33,9 +34,7 @@
3334
import java.io.Reader;
3435
import java.io.Writer;
3536
import java.nio.ByteBuffer;
36-
import java.util.LinkedHashMap;
37-
import java.util.List;
38-
import java.util.Map;
37+
import java.util.*;
3938

4039
/**
4140
* Converts deep hierarchical Avro records into flat CSV format. It uses a simple dot syntax in the
@@ -62,7 +61,7 @@ public boolean hasHeader() {
6261
private final ObjectWriter csvWriter;
6362
private final Map<String, Object> map;
6463
private final CsvGenerator generator;
65-
private final int numOfColumns;
64+
private CsvSchema schema;
6665

6766
public CsvAvroConverter(CsvFactory factory, Writer writer, GenericRecord record, boolean writeHeader, Reader reader)
6867
throws IOException {
@@ -71,7 +70,7 @@ public CsvAvroConverter(CsvFactory factory, Writer writer, GenericRecord record,
7170
CsvMapper mapper = new CsvMapper(factory);
7271
Map<String, Object> value;
7372

74-
CsvSchema schema = CsvSchema.emptySchema().withHeader();
73+
schema = CsvSchema.emptySchema().withHeader();
7574
if (!writeHeader) {
7675
// If file already exists read the schema from the CSV file
7776
ObjectReader objectReader = mapper.readerFor(Map.class).with(schema);
@@ -93,7 +92,6 @@ public CsvAvroConverter(CsvFactory factory, Writer writer, GenericRecord record,
9392

9493
generator = factory.createGenerator(writer);
9594
csvWriter = mapper.writer(schema);
96-
numOfColumns = schema.size();
9795

9896
}
9997

@@ -107,10 +105,21 @@ public CsvAvroConverter(CsvFactory factory, Writer writer, GenericRecord record,
107105
public boolean writeRecord(GenericRecord record) throws IOException {
108106
Map<String, Object> localMap = convertRecord(record);
109107

110-
if(localMap.size() > numOfColumns) {
108+
if(localMap.size() > schema.size()) {
111109
// Cannot write to same file so return false
112110
return false;
111+
} else {
112+
Iterator<String> localColumnIterator = localMap.keySet().iterator();
113+
for(int i = 0; i < schema.size(); i++) {
114+
if (!schema.columnName(i).equals(localColumnIterator.next())) {
115+
/* The order or name of columns is different and
116+
thus cannot write to this csv file. return false.
117+
*/
118+
return false;
119+
}
120+
}
113121
}
122+
114123
csvWriter.writeValue(generator, localMap);
115124
localMap.clear();
116125
return true;

src/test/java/org/radarcns/util/CsvAvroConverterTest.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,31 @@ public void differentSchema() throws IOException {
116116
Schema schemaB = SchemaBuilder.record("B").fields().name("b").type("string").noDefault().endRecord();
117117
GenericRecord recordB = new GenericRecordBuilder(schemaB).set("b", "something").build();
118118

119-
exception.expect(JsonMappingException.class);
120-
converter.writeRecord(recordB);
119+
/* Same number of columns but different schema, so CsvAvroConverter.write() will return false
120+
signifying that a new CSV file must be used to write this record
121+
*/
122+
assertFalse(converter.writeRecord(recordB));
123+
System.out.println(writer.toString());
124+
}
125+
126+
127+
@Test
128+
public void differentSchema2() throws IOException {
129+
Schema schemaA = SchemaBuilder.record("A").fields().name("a").type("string").noDefault().name("b").type("string").noDefault().endRecord();
130+
GenericRecord recordA = new GenericRecordBuilder(schemaA).set("a", "something").set("b", "2nd something").build();
131+
132+
StringWriter writer = new StringWriter();
133+
RecordConverter converter = CsvAvroConverter.getFactory().converterFor(writer, recordA, true, new StringReader("test"));
134+
converter.writeRecord(recordA);
135+
136+
Schema schemaB = SchemaBuilder.record("B").fields().name("b").type("string").noDefault().name("a").type("string").noDefault().endRecord();
137+
GenericRecord recordB = new GenericRecordBuilder(schemaB).set("b", "something").set("a", "2nd something").build();
138+
139+
/* Same number of columns and same header but different order,
140+
so CsvAvroConverter.write() will return false signifying that
141+
a new CSV file must be used to write this record
142+
*/
143+
assertFalse(converter.writeRecord(recordB));
121144
System.out.println(writer.toString());
122145
}
123146

0 commit comments

Comments
 (0)