Skip to content

Commit 140eaba

Browse files
Internal refactoring
1 parent 7e2c483 commit 140eaba

File tree

8 files changed

+120
-30
lines changed

8 files changed

+120
-30
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>io.frictionlessdata</groupId>
55
<artifactId>tableschema-java</artifactId>
6-
<version>0.7.3-SNAPSHOT</version>
6+
<version>0.7.4-SNAPSHOT</version>
77
<packaging>jar</packaging>
88
<issueManagement>
99
<url>https://github.com/frictionlessdata/tableschema-java/issues</url>

src/main/java/io/frictionlessdata/tableschema/Table.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ public List<Object[]> read(boolean cast){
366366
if(cast && (null == schema)){
367367
throw new TableSchemaException("Cannot cast without a schema");
368368
}
369-
if(cast && !this.schema.hasFields()){
369+
if(cast && this.schema.isEmpty()){
370370
throw new InvalidCastException("Schema has no fields");
371371
}
372372

@@ -475,7 +475,7 @@ public void write(Writer out, TableDataSource.Format dataFormat) {
475475
try {
476476
String[] headers;
477477
if (null != schema) {
478-
List<String> fieldNames = schema.getFieldNames();
478+
List<String> fieldNames = schema.getFields().stream().map(Field::getName).toList();
479479
headers = fieldNames.toArray(new String[0]);
480480
} else {
481481
headers = dataSource.getHeaders();
@@ -550,7 +550,7 @@ public void validate() throws TableValidationException, TableSchemaException {
550550
if (null == headers) {
551551
return;
552552
}
553-
List<String> declaredHeaders = schema.getFieldNames();
553+
List<String> declaredHeaders = schema.getFields().stream().map(Field::getName).toList();
554554
List<String> foundHeaders = Arrays.asList(headers);
555555
//If we have JSON data, fields with `null` values might be omitted, therefore do not do a strict check
556556
if (dataSource.hasReliableHeaders()) {

src/main/java/io/frictionlessdata/tableschema/field/NumberField.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public Number parseValue(String value, String format, Map<String, Object> option
8787
throw new TypeInferringException();
8888
}
8989
}
90+
@Override
9091
public Object formatValueForJson(Number value) throws InvalidCastException, ConstraintsException {
9192
return formatValueAsString(value, null, options);
9293
}

src/main/java/io/frictionlessdata/tableschema/schema/BeanSchema.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
import static io.frictionlessdata.tableschema.util.ReflectionUtil.getBeanDescription;
2828

29+
/**
30+
* This replaces the normal Schema for reading a Table. It creates a Schema based on a Java Bean class.
31+
*/
2932
public class BeanSchema extends Schema {
3033

3134
@JsonIgnore
@@ -46,6 +49,7 @@ public static BeanSchema infer(Class<?> beanClass) {
4649
}
4750

4851
@JsonIgnore
52+
@Override
4953
public String[] getHeaders() {
5054
List<String> retVal = new ArrayList<>();
5155
Iterator<CsvSchema.Column> iterator = csvSchema.iterator();
@@ -55,6 +59,7 @@ public String[] getHeaders() {
5559
return retVal.toArray(new String[]{});
5660
}
5761

62+
@Override
5863
public Field<?> getField(String name) {
5964
return fieldMap.get(name);
6065
}

src/main/java/io/frictionlessdata/tableschema/schema/Schema.java

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
*/
4545
@JsonIgnoreProperties(ignoreUnknown = true)
4646
@JsonInclude(value = Include.NON_EMPTY)
47-
public class Schema {
47+
public class Schema implements SchemaInterface{
4848
private static final Logger log = LoggerFactory.getLogger(Schema.class);
4949

5050
public static final String JSON_KEY_FIELDS = "fields";
@@ -213,6 +213,7 @@ public static Schema infer(List<Object[]> data, String[] headers, int rowLimit)
213213
*
214214
* @return true if schema is valid
215215
*/
216+
@Override
216217
@JsonIgnore
217218
public boolean isValid() {
218219
try {
@@ -229,12 +230,13 @@ public void writeJson(File outputFile) throws IOException {
229230
}
230231
}
231232

232-
public void writeJson(OutputStream output) throws IOException {
233+
private void writeJson(OutputStream output) throws IOException {
233234
try (BufferedWriter file = new BufferedWriter(new OutputStreamWriter(output))) {
234235
file.write(this.asJson());
235236
}
236237
}
237238

239+
@Override
238240
public void addField(Field<?> field) {
239241
this.fields.add(field);
240242
this.validate();
@@ -250,6 +252,7 @@ public void addField(String json) {
250252
this.addField(field);
251253
}
252254

255+
@Override
253256
public List<Field<?>> getFields() {
254257
return this.fields;
255258
}
@@ -259,7 +262,8 @@ public List<Field<?>> getFields() {
259262
*
260263
* @return the matching Field or null if no name matches
261264
*/
262-
public Field getField(String name) {
265+
@Override
266+
public Field<?> getField(String name) {
263267
for (Field<?> field : this.fields) {
264268
if (field.getName().equalsIgnoreCase(name)) {
265269
return field;
@@ -269,13 +273,14 @@ public Field getField(String name) {
269273
}
270274

271275
@JsonIgnore
272-
public List<String> getFieldNames() {
276+
List<String> getFieldNames() {
273277
return fields
274278
.stream()
275279
.map(Field::getName)
276280
.collect(Collectors.toList());
277281
}
278282

283+
@Override
279284
@JsonIgnore
280285
public String[] getHeaders() {
281286
return getFieldNames().toArray(new String[0]);
@@ -286,7 +291,7 @@ public String[] getHeaders() {
286291
*
287292
* @return true if a field with the given names exists or false if no name matches
288293
*/
289-
public boolean hasField(String name) {
294+
boolean hasField(String name) {
290295
Field<?> field = fields
291296
.stream()
292297
.filter((f) -> f.getName().equals(name))
@@ -295,10 +300,16 @@ public boolean hasField(String name) {
295300
return (null != field);
296301
}
297302

298-
public boolean hasFields() {
303+
@Deprecated
304+
boolean hasFields() {
299305
return !this.getFields().isEmpty();
300306
}
301307

308+
@Override
309+
@JsonIgnore
310+
public boolean isEmpty() {
311+
return this.getFields().isEmpty();
312+
}
302313

303314
@SuppressWarnings("unchecked")
304315
public <Any> Any getPrimaryKey() {
@@ -321,7 +332,7 @@ public <Any> Any getPrimaryKey() {
321332
}
322333

323334
@JsonIgnore
324-
public List<String> getPrimaryKeyParts() {
335+
List<String> getPrimaryKeyParts() {
325336
if (primaryKey instanceof String)
326337
return Collections.singletonList((String) primaryKey);
327338
if (primaryKey instanceof ArrayNode) {
@@ -332,11 +343,12 @@ public List<String> getPrimaryKeyParts() {
332343
throw new TableSchemaException("Unknown PrimaryKey type: " + primaryKey.getClass());
333344
}
334345

346+
@Override
335347
public List<ForeignKey> getForeignKeys() {
336348
return this.foreignKeys;
337349
}
338350

339-
351+
@Override
340352
public List<ValidationException> getErrors(){
341353
return this.errors;
342354
}
@@ -356,10 +368,6 @@ public String asJson() {
356368
return JsonUtil.getInstance().serialize(this);
357369
}
358370

359-
public FileReference<?> getReference() {
360-
return reference;
361-
}
362-
363371
/**
364372
* Set single primary key with the option of validation.
365373
*
@@ -383,12 +391,12 @@ public void setPrimaryKey(String[] keys) throws PrimaryKeyException {
383391
* @throws PrimaryKeyException if this Schema does not contain fields listed in the `compositeKey` and
384392
* validation is set to strict
385393
*/
386-
public void setPrimaryKey(ArrayNode compositeKey) throws PrimaryKeyException {
394+
private void setPrimaryKey(ArrayNode compositeKey) throws PrimaryKeyException {
387395
compositeKey.forEach(k -> checkKey(k.asText()));
388396
this.primaryKey = compositeKey;
389397
}
390398

391-
public void addForeignKey(ForeignKey foreignKey) {
399+
void addForeignKey(ForeignKey foreignKey) {
392400
this.foreignKeys.add(foreignKey);
393401
}
394402

@@ -440,6 +448,7 @@ public int hashCode() {
440448
*
441449
* @throws ValidationException If validation fails and validation is strict
442450
*/
451+
@Override
443452
@JsonIgnore
444453
public void validate() throws ValidationException{
445454
String json = this.asJson();
Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,81 @@
11
package io.frictionlessdata.tableschema.schema;
22

3+
import io.frictionlessdata.tableschema.exception.ValidationException;
4+
import io.frictionlessdata.tableschema.field.Field;
5+
import io.frictionlessdata.tableschema.fk.ForeignKey;
6+
37
import java.util.List;
48

9+
/**
10+
* Interface for Schema implementations according to the
11+
* Table Schema specification from https://specs.frictionlessdata.io//table-schema/index.html
12+
*
13+
* Table Schema is a simple language- and implementation-agnostic way to declare a schema for tabular data.
14+
* Table Schema is well suited for use cases around handling and validating tabular data in text formats such as CSV,
15+
* but its utility extends well beyond this core usage, towards a range of applications where data benefits
16+
* from a portable schema format
17+
*/
518
public interface SchemaInterface {
619

20+
/**
21+
* Get the fields of the schema.
22+
* @return a list of fields
23+
*/
24+
List<Field<?>> getFields();
25+
26+
/**
27+
* Retrieve a field by its `name` property.
28+
*
29+
* @param name the name of the field
30+
* @return the matching Field or null if no name matches
31+
*/
32+
Field<?> getField(String name);
33+
34+
/**
35+
* Add a field to the schema.
36+
* @param field the field to add
37+
*/
38+
void addField(Field<?> field);
39+
40+
/**
41+
* Return all the foreign key definitions of the schema.
42+
*
43+
* @return a list of {@link ForeignKey} objects
44+
*/
45+
List<ForeignKey> getForeignKeys();
46+
47+
/**
48+
* Check if schema is valid or not.
49+
*
50+
* @return true if schema is valid
51+
*/
752
boolean isValid();
853

54+
/**
55+
* Check if schema has any fields.
56+
*
57+
* @return true if schema has no fields
58+
*/
59+
boolean isEmpty();
60+
61+
/**
62+
* Validate the loaded Schema. Failed validation
63+
* will lead to a ValidationException thrown.
64+
*
65+
* @throws ValidationException If validation fails and validation is strict
66+
*/
967
void validate();
1068

11-
List<Exception> getErrors();
69+
/**
70+
* Get the header names of the underlying data source(s).
71+
*
72+
* @return header names as a String array
73+
*/
74+
String[] getHeaders();
75+
76+
/**
77+
* return the errors that occurred during validation
78+
* @return a list of ValidationExceptions
79+
*/
80+
List<ValidationException> getErrors();
1281
}

src/main/java/io/frictionlessdata/tableschema/util/JsonUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ public JsonNode readValue(InputStream value) {
138138
throw new JsonParsingException(e);
139139
}
140140
}
141+
142+
public <T> T convertValue(Object value, TypeReference<T> ref) {
143+
return mapper.convertValue(value, ref);
144+
}
141145

142146
public <T> T convertValue(Object value, Class<T> clazz) {
143147
return mapper.convertValue(value, clazz);

src/test/java/io/frictionlessdata/tableschema/schema/SchemaTest.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,17 @@ public void testAddValidFieldAsJson() {
202202
@Test
203203
public void hasField() {
204204
Schema schema = new Schema();
205-
Assertions.assertFalse(schema.hasFields());
205+
Assertions.assertTrue(schema.isEmpty());
206206

207207
Field<?> idField = new IntegerField("id");
208208
schema.addField(idField);
209-
Assertions.assertTrue(schema.hasFields());
209+
Assertions.assertFalse(schema.isEmpty());
210210
}
211211

212212
@Test
213213
public void hasSetField() {
214214
Schema schema = new Schema();
215-
Assertions.assertFalse(schema.hasFields());
215+
Assertions.assertTrue(schema.isEmpty());
216216

217217
Field<?> idField = new IntegerField("id");
218218
schema.addField(idField);
@@ -533,10 +533,11 @@ public void testSaveDefaultBooleanValues() throws Exception {
533533
Schema readSchema = Schema.fromJson(createdFile, true);
534534
Assertions.assertEquals(createdSchema, readSchema);
535535

536-
Assertions.assertEquals("true", readSchema.getField("isAdmin").formatValueAsString(true));
537-
Assertions.assertEquals("false", readSchema.getField("isAdmin").formatValueAsString(false));
538-
Assertions.assertEquals("true", createdSchema.getField("isAdmin").formatValueAsString(true));
539-
Assertions.assertEquals("false", createdSchema.getField("isAdmin").formatValueAsString(false));
536+
BooleanField adminField = ((BooleanField)readSchema.getField("isAdmin"));
537+
Assertions.assertEquals("true", adminField.formatValueAsString(true));
538+
Assertions.assertEquals("false", adminField.formatValueAsString(false));
539+
Assertions.assertEquals("true", adminField.formatValueAsString(true));
540+
Assertions.assertEquals("false", adminField.formatValueAsString(false));
540541
}
541542

542543

@@ -551,10 +552,11 @@ public void testSaveAlternateBooleanValues() throws Exception {
551552
Schema readSchema = Schema.fromJson(createdFile, true);
552553
Assertions.assertEquals(createdSchema, readSchema);
553554

554-
Assertions.assertEquals("TRUE", readSchema.getField("isAdmin").formatValueAsString(true));
555-
Assertions.assertEquals("FALSE", readSchema.getField("isAdmin").formatValueAsString(false));
556-
Assertions.assertEquals("TRUE", createdSchema.getField("isAdmin").formatValueAsString(true));
557-
Assertions.assertEquals("FALSE", createdSchema.getField("isAdmin").formatValueAsString(false));
555+
BooleanField adminField = ((BooleanField)readSchema.getField("isAdmin"));
556+
Assertions.assertEquals("TRUE", adminField.formatValueAsString(true));
557+
Assertions.assertEquals("FALSE", adminField.formatValueAsString(false));
558+
Assertions.assertEquals("TRUE", adminField.formatValueAsString(true));
559+
Assertions.assertEquals("FALSE", adminField.formatValueAsString(false));
558560
}
559561

560562

0 commit comments

Comments
 (0)