Skip to content

Commit

Permalink
#9: Initial implementation of Streaming and reading of resources thro…
Browse files Browse the repository at this point in the history
…ugh a table schema with cast on iteration.
  • Loading branch information
Georges Labrèche committed Nov 28, 2017
1 parent 84dc6ac commit 8689bb1
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 10 deletions.
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,13 @@
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>

<!-- Commons CSV: https://commons.apache.org/proper/commons-csv/ -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.5</version>
</dependency>

</dependencies>
</project>
11 changes: 11 additions & 0 deletions src/main/java/io/frictionlessdata/datapackage/Profile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.frictionlessdata.datapackage;

/**
*
*
*/
public class Profile {
public final static String PROFILE_DEFAULT = "data-package";
public static final String PROFILE_TABULAR_DATA_RESOURCE = "tabular-data-resource";

}
107 changes: 107 additions & 0 deletions src/main/java/io/frictionlessdata/datapackage/Resource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package io.frictionlessdata.datapackage;

import io.frictionlessdata.datapackage.exceptions.DataPackageException;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;

/**
* Resource.
* Based on specs: http://frictionlessdata.io/specs/data-resource/
*/
public class Resource {

// Data properties.
private String path = null;
private Object data = null;

// Metadata properties.
// Required properties.
private String name = null;

// Recommended properties.
private String profile = null;

// Optional properties.
private String title = null;
private String description = null;
private String format = null;
private String mediaType = null;
private String encoding = null;
private Integer bytes = null;
private String hash = null;

// hashes and licenes?

public Resource(String name, String path){
this.name = name;
this.path = path;
}

public Resource(String name, Object data, String format){
this.name = name;
this.data = data;
this.format = format;
}

public Iterable<CSVRecord> iter() throws IOException, FileNotFoundException, DataPackageException{
// Error for non tabular
if(this.profile.equalsIgnoreCase(Profile.PROFILE_TABULAR_DATA_RESOURCE)){
throw new DataPackageException("Unsupported for non tabular data.");
}

if(this.path != null){
Reader in = new FileReader(this.path);
Iterable<CSVRecord> csvRecords = CSVFormat.RFC4180.parse(in);

return csvRecords;

}else if (this.data != null){
return null;

}else{
throw new DataPackageException("No data has been set.");
}
}

public void read() throws DataPackageException{
if(this.profile.equalsIgnoreCase(Profile.PROFILE_TABULAR_DATA_RESOURCE)){
throw new DataPackageException("Unsupported for non tabular data.");
}

if(path != null){

}else if (data != null){

}else{
throw new DataPackageException("No data has been set.");
}
}

public String getProfile(){
return this.profile;
}

public void setProfile(String profile){
this.profile = profile;
}

public String getTitle(){
return this.title;
}

public void setTitle(String title){
this.title = title;
}

public String getDescription(){
return this.description;
}

public void setDescription(String description){
this.description = description;
}
}
4 changes: 2 additions & 2 deletions src/main/java/io/frictionlessdata/datapackage/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
public class Validator {

private final static String PROFILE_DEFAULT = "data-package";


/**
* Validates a given JSON Object against the default profile schema.
Expand All @@ -43,7 +43,7 @@ public void validate(JSONObject datapackageJsonObject) throws IOException, DataP

}else{
// If no profile value is provided, use default value.
this.validate(datapackageJsonObject, PROFILE_DEFAULT);
this.validate(datapackageJsonObject, Profile.PROFILE_DEFAULT);
}
}

Expand Down
54 changes: 54 additions & 0 deletions src/test/java/io/frictionlessdata/datapackage/ResourceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.frictionlessdata.datapackage;

import io.frictionlessdata.datapackage.exceptions.DataPackageException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.csv.CSVRecord;
import org.junit.Assert;
import org.junit.Test;

/**
*
*
*/
public class ResourceTest {

@Test
public void testValidationWithValidProfileUrl() throws IOException, DataPackageException, MalformedURLException{

URL url = new URL("https://raw.githubusercontent.com/frictionlessdata/datapackage-java/master/src/test/resources/fixtures/valid_population_datapackage.json");
Resource resource = new Resource("population", url, "csv");

// Set the profile to tabular data resource.
resource.setProfile(Profile.PROFILE_TABULAR_DATA_RESOURCE);

// Expected data.
List<String[]> expectedData = new ArrayList();
expectedData.add(new String[]{"city", "year", "population"});
expectedData.add(new String[]{"london", "2017", "8780000"});
expectedData.add(new String[]{"paris", "2017", "2240000"});
expectedData.add(new String[]{"rome", "2017", "2860000"});

// Get iterator.
Iterable<CSVRecord> records = resource.iter();
int expectedDataIndex = 0;

// Assert data.
for (CSVRecord record : records) {
String city = record.get(0);
String year = record.get(1);
String population = record.get(2);

Assert.assertEquals(expectedData.get(expectedDataIndex)[0], city);
Assert.assertEquals(expectedData.get(expectedDataIndex)[1], year);
Assert.assertEquals(expectedData.get(expectedDataIndex)[2], population);

expectedDataIndex++;
}

}

}
8 changes: 4 additions & 4 deletions src/test/resources/fixtures/data/area.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
city,year,population
london,2017,8780000
paris,2017,2240000
rome,2017,2860000
city,year,area_km2
london,2017,1572
paris,2017,105.4
rome,2017,1285
8 changes: 4 additions & 4 deletions src/test/resources/fixtures/data/population.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
city,year,area_km2
london,2017,1572
paris,2017,105.4
rome,2017,1285
city,year,population
london,2017,8780000
paris,2017,2240000
rome,2017,2860000
17 changes: 17 additions & 0 deletions src/test/resources/fixtures/valid_population_datapackage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "world",
"resources": [
{
"name": "population",
"path": "data/population.csv",
"profile":"tabular-data-resource",
"schema": {
"fields": [
{"name": "city", "type": "string"},
{"name": "year", "type": "integer"},
{"name": "population", "type": "integer"}
]
}
}
]
}

0 comments on commit 8689bb1

Please sign in to comment.