Skip to content

Commit b4ea07b

Browse files
Simplification to Resource definition
1 parent cf954be commit b4ea07b

File tree

23 files changed

+1271
-181
lines changed

23 files changed

+1271
-181
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>io.frictionlessdata</groupId>
66
<artifactId>datapackage-java</artifactId>
7-
<version>0.7.5-SNAPSHOT</version>
7+
<version>0.8.0-SNAPSHOT</version>
88
<packaging>jar</packaging>
99
<issueManagement>
1010
<url>https://github.com/frictionlessdata/datapackage-java/issues</url>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package io.frictionlessdata.datapackage;
2+
3+
import java.util.List;
4+
5+
public interface BaseInterface {
6+
7+
/**
8+
* @return the name
9+
*/
10+
String getName();
11+
12+
/**
13+
* @param name the name to set
14+
*/
15+
void setName(String name);
16+
17+
/**
18+
* @return the profile
19+
*/
20+
String getProfile();
21+
22+
/**
23+
* @param profile the profile to set
24+
*/
25+
void setProfile(String profile);
26+
27+
/**
28+
* @return the title
29+
*/
30+
String getTitle();
31+
32+
/**
33+
* @param title the title to set
34+
*/
35+
void setTitle(String title);
36+
37+
/**
38+
* @return the description
39+
*/
40+
String getDescription();
41+
42+
/**
43+
* @param description the description to set
44+
*/
45+
void setDescription(String description);
46+
47+
48+
/**
49+
* @return the sources
50+
*/
51+
List<Source> getSources();
52+
53+
/**
54+
* @param sources the sources to set
55+
*/
56+
void setSources(List<Source> sources);
57+
58+
/**
59+
* @return the licenses
60+
*/
61+
List<License> getLicenses();
62+
63+
/**
64+
* @param licenses the licenses to set
65+
*/
66+
void setLicenses(List<License> licenses);
67+
68+
/**
69+
* @return the encoding
70+
*/
71+
String getEncoding();
72+
73+
/**
74+
* @param encoding the encoding to set
75+
*/
76+
void setEncoding(String encoding);
77+
78+
/**
79+
* @return the bytes
80+
*/
81+
Integer getBytes();
82+
83+
/**
84+
* @param bytes the bytes to set
85+
*/
86+
void setBytes(Integer bytes);
87+
88+
/**
89+
* @return the hash
90+
*/
91+
String getHash();
92+
93+
/**
94+
* @param hash the hash to set
95+
*/
96+
void setHash(String hash);
97+
98+
/**
99+
* @return the mediaType
100+
*/
101+
String getMediaType();
102+
103+
/**
104+
* @param mediaType the mediaType to set
105+
*/
106+
void setMediaType(String mediaType);
107+
108+
}

src/main/java/io/frictionlessdata/datapackage/JSONBase.java

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.fasterxml.jackson.annotation.JsonInclude.Include;
55
import com.fasterxml.jackson.core.type.TypeReference;
66
import com.fasterxml.jackson.databind.JsonNode;
7-
import com.fasterxml.jackson.databind.node.ArrayNode;
87
import com.fasterxml.jackson.databind.node.ObjectNode;
98
import com.fasterxml.jackson.databind.node.TextNode;
109
import io.frictionlessdata.datapackage.exceptions.DataPackageException;
@@ -35,8 +34,7 @@
3534
import static io.frictionlessdata.datapackage.Validator.isValidUrl;
3635

3736
@JsonInclude(value = Include.NON_EMPTY, content = Include.NON_EMPTY )
38-
public abstract class JSONBase {
39-
static final int JSON_INDENT_FACTOR = 4;// JSON keys.
37+
public abstract class JSONBase implements BaseInterface {
4038
public static final String JSON_KEY_NAME = "name";
4139
public static final String JSON_KEY_PROFILE = "profile";
4240
public static final String JSON_KEY_PATH = "path";
@@ -68,13 +66,11 @@ public abstract class JSONBase {
6866
protected String title = null;
6967
protected String description = null;
7068

71-
String format = null;
7269
protected String mediaType = null;
7370
protected String encoding = null;
7471
protected Integer bytes = null;
7572
protected String hash = null;
7673

77-
Dialect dialect;
7874
private List<Source> sources = null;
7975
private List<License> licenses = null;
8076

@@ -97,20 +93,6 @@ public abstract class JSONBase {
9793
*/
9894
public String getProfile(){return profile;}
9995

100-
/**
101-
* @param profile the profile to set
102-
*/
103-
public void setProfile(String profile){
104-
if (profile.equals(Profile.PROFILE_TABULAR_DATA_PACKAGE)) {
105-
if (this instanceof Package) {
106-
107-
} else if (this instanceof Resource) {
108-
throw new DataPackageValidationException("Cannot set "+Profile.PROFILE_TABULAR_DATA_PACKAGE+" on a resource");
109-
}
110-
}
111-
this.profile = profile;
112-
}
113-
11496
/**
11597
* @return the title
11698
*/

src/main/java/io/frictionlessdata/datapackage/Package.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,11 @@ public void writeJson (OutputStream output) throws IOException{
652652
*/
653653
final void validate() throws IOException, DataPackageException{
654654
try{
655-
Validator.validate(this.getJsonNode());
655+
ObjectNode jsonNode = this.getJsonNode();
656+
for (Resource r : this.getResources()) {
657+
r.validate(this);
658+
}
659+
Validator.validate(jsonNode);
656660
} catch(ValidationException | DataPackageException ve){
657661
if (this.strictValidation){
658662
throw ve;
@@ -809,7 +813,7 @@ private void setJson(ObjectNode jsonNodeSource) throws Exception {
809813
this.setProperty(k, obj);
810814
}
811815
});
812-
resources.forEach(Resource::validate);
816+
resources.forEach((r) -> r.validate(this));
813817
validate();
814818
}
815819

src/main/java/io/frictionlessdata/datapackage/Validator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ public static void validate(JsonNode jsonObjectToValidate) throws IOException, D
4848
}
4949

5050
if (!errors.isEmpty()) {
51-
throw new ValidationException("Error validating Schema", "profile id: " + profileId, errors);
51+
throw new ValidationException(profileId, errors);
5252
}
5353
}
5454

5555
/**
56-
* Validates a given JSON Object against the a given profile schema.
56+
* Validates a given JSON Object against a given profile schema.
5757
*
5858
* @param jsonObjectToValidate
5959
* @param profileId
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package io.frictionlessdata.datapackage.fk;
2+
3+
import io.frictionlessdata.datapackage.Package;
4+
import io.frictionlessdata.datapackage.resource.Resource;
5+
import io.frictionlessdata.tableschema.Table;
6+
import io.frictionlessdata.tableschema.exception.ForeignKeyException;
7+
import io.frictionlessdata.tableschema.field.Field;
8+
import io.frictionlessdata.tableschema.fk.ForeignKey;
9+
import io.frictionlessdata.tableschema.fk.Reference;
10+
import io.frictionlessdata.tableschema.schema.Schema;
11+
12+
import java.util.*;
13+
14+
/**
15+
* PackageForeignKey is a wrapper around the ForeignKey class to validate foreign keys
16+
* in the context of a data package. It checks if the referenced resource and fields exist
17+
* in the data package and validates the foreign key constraints.
18+
*
19+
* This class exists because the specification of foreign keys in the tableschema specification
20+
* is a bit awkward: it assumes that the target of a foreign key can be resolved to a different table, which is
21+
* only possible on a datapackage level, yet the foreign key is defined as part of a Schema.
22+
*
23+
* In our implementation therefore, we have a ForeignKey class in the TableSchema package which only can
24+
* validate self-referencing FKs. This class is used to resolve FKs to different resources of a package
25+
*/
26+
public class PackageForeignKey {
27+
28+
private ForeignKey fk;
29+
private Package datapackage;
30+
private Resource<?> resource;
31+
32+
public PackageForeignKey(ForeignKey fk, Resource<?> res, Package pkg) {
33+
this.datapackage = pkg;
34+
this.resource = res;
35+
this.fk = fk;
36+
}
37+
38+
public void validate() throws Exception {
39+
Reference reference = fk.getReference();
40+
// self-reference, this can be validated by the Tableschema {@link ForeignKey} class
41+
if (reference.getResource().equals("")) {
42+
for (Table table : resource.getTables()) {
43+
fk.validate(table);
44+
}
45+
} else {
46+
// validate the foreign key
47+
Resource<?> refResource = datapackage.getResource(reference.getResource());
48+
if (refResource == null) {
49+
throw new ForeignKeyException("Reference resource not found: " + reference.getResource());
50+
}
51+
List<String> fieldNames = new ArrayList<>();
52+
List<String> foreignFieldNames = new ArrayList<>();
53+
List<String> lFields = fk.getFieldNames();
54+
Schema foreignSchema = refResource.getSchema();
55+
if (null == foreignSchema) {
56+
foreignSchema = refResource.inferSchema();
57+
}
58+
for (int i = 0; i < lFields.size(); i++) {
59+
fieldNames.add(lFields.get(i));
60+
String foreignFieldName = reference.getFieldNames().get(i);
61+
foreignFieldNames.add(foreignFieldName);
62+
Field<?> foreignField = foreignSchema.getField(foreignFieldName);
63+
if (null == foreignField) {
64+
throw new ForeignKeyException("Foreign key ["+fieldNames.get(i)+ "-> "
65+
+reference.getFieldNames().get(i)+"] violation : expected: "
66+
+reference.getFieldNames().get(i) + ", but not found");
67+
}
68+
}
69+
70+
}
71+
}
72+
}

src/main/java/io/frictionlessdata/datapackage/resource/AbstractDataResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*
1919
* @param <T> the data format, either CSV or JSON array
2020
*/
21-
public abstract class AbstractDataResource<T,C> extends AbstractResource<T,C> {
21+
public abstract class AbstractDataResource<T,C> extends AbstractResource<T> {
2222
T data;
2323

2424
AbstractDataResource(String name, T data) {

src/main/java/io/frictionlessdata/datapackage/resource/AbstractReferencebasedResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import java.util.*;
1414
import java.util.stream.Collectors;
1515

16-
public abstract class AbstractReferencebasedResource<T,C> extends AbstractResource<T,C> {
16+
public abstract class AbstractReferencebasedResource<T,C> extends AbstractResource<T> {
1717
Collection<T> paths;
1818

1919
AbstractReferencebasedResource(String name, Collection<T> paths) {

0 commit comments

Comments
 (0)