diff --git a/.coveralls.yml b/.coveralls.yml
deleted file mode 100644
index 6e64999..0000000
--- a/.coveralls.yml
+++ /dev/null
@@ -1 +0,0 @@
-service_name: travis-ci
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..a707323
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ - package-ecosystem: "maven"
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "monthly"
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..1ecd864
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,28 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
+ - name: Run test and coverage report
+ run: mvn clean test jacoco:report
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index dcd69a6..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-dist:
- trusty
-
-sudo:
- false
-
-language:
- java
-
-jdk:
- - oraclejdk8
-
-install: mvn install -DskipTests -Dgpg.skip -Dmaven.javadoc.skip=true -B -V
-
-after_success:
- - mvn clean test jacoco:report coveralls:report
diff --git a/README.md b/README.md
index f602e71..7e49ad2 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,27 @@
-
# datapackage-java
-A Java library for working with Data Packages. Snapshots on [Jitpack](https://jitpack.io/#frictionlessdata/datapackage-java)
-
-[](https://travis-ci.org/frictionlessdata/datapackage-java)
-[](https://coveralls.io/github/frictionlessdata/datapackage-java?branch=master)
[](https://github.com/frictionlessdata/datapackage-java/blob/master/LICENSE)
-[](https://github.com/frictionlessdata/datapackage-java/tree/master/)
-[](https://jitpack.io/#frictionlessdata/datapackage-java)
-[](https://gitter.im/frictionlessdata/chat)
+[](https://jitpack.io/#frictionlessdata/datapackage-java)
+[](https://github.com/frictionlessdata/datapackage-java)
+[](https://discordapp.com/invite/Sewv6av)
+A Java library for working with Data Packages according to the
+[Frictionless Data](https://specs.frictionlessdata.io/data-package/) specifications.
+A Data Package is a simple container format for creating self-contained packages of data. It provides the basis
+for convenient delivery, installation and management of datasets. It shares some similarity with simple database
+formats, but lacks a robust query engine, instead focusing on exchanging bundles of related data.
+
+Please find releases on [Jitpack](https://jitpack.io/#frictionlessdata/datapackage-java)
## Usage
+- [Create a Data Package](#create_a_data_package) explains how to create a Data Package
+- [Iterate through Data](#iterate_through_data) explains how to iterate through data in Resources
+- [Edit a Data Package](#edit_a_data_package) explains how to add or remove Resources or properties to or from a Data Package
+- [Save to File](#save_to_file) explains how to save a Data Package to a file
+- [Working with Foreign Keys](docs/foreign-keys.md) explains how to set foreign key constraints in Data Packages
+- [Contributing](#contributing) contributions are welcome
+
### Create a Data Package
#### From JSONObject Object
@@ -204,6 +213,7 @@ dp.save("/destination/path/datapackage.zip")
Found a problem and would like to fix it? Have that great idea and would love to see it in the repository?
+> [!NOTE]
> Please open an issue before you start working.
It could save a lot of time for everyone and we are super happy to answer questions and help you along the way. Furthermore, feel free to join [frictionlessdata Gitter chat room](https://gitter.im/frictionlessdata/chat) and ask questions.
@@ -213,9 +223,9 @@ This project follows the [Open Knowledge International coding standards](https:/
Get started:
```sh
# install jabba and maven2
-$ cd tableschema-java
-$ jabba install 1.8
-$ jabba use 1.8
+$ cd datapackage-java
+$ jabba install 17
+$ jabba use 17
$ mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
$ mvn test -B
```
diff --git a/docs/foreign-keys.md b/docs/foreign-keys.md
new file mode 100644
index 0000000..104aa2c
--- /dev/null
+++ b/docs/foreign-keys.md
@@ -0,0 +1,80 @@
+# Working with Foreign Keys
+
+The library supports foreign keys described in the [Table Schema](http://specs.frictionlessdata.io/table-schema/#foreign-keys) specification. It means if your data package descriptor use `resources[].schema.foreignKeys` property for some resources a data integrity will be checked on reading operations.
+
+Consider we have a data package:
+
+```json
+{
+ "name": "foreign-keys",
+ "resources": [
+ {
+ "name": "teams",
+ "data": [
+ ["id", "name", "city"],
+ ["1", "Arsenal", "London"],
+ ["2", "Real", "Madrid"],
+ ["3", "Bayern", "Munich"]
+ ],
+ "schema": {
+ "fields": [
+ {
+ "name": "id",
+ "type": "integer"
+ },
+ {
+ "name": "name",
+ "type": "string"
+ },
+ {
+ "name": "city",
+ "type": "string"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "fields": "city",
+ "reference": {
+ "resource": "cities",
+ "fields": "name"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "cities",
+ "data": [
+ ["name", "country"],
+ ["London", "England"],
+ ["Madrid", "Spain"]
+ ]
+ }
+ ]
+}
+```
+
+Let's check relations for a `teams` resource:
+
+````java
+Package dp = new Package(DESCRIPTOR, Paths.get(""), true);
+ Resource teams = dp.getResource("teams");
+ DataPackageValidationException dpe
+ = Assertions.assertThrows(DataPackageValidationException.class, () -> teams.checkRelations(dp));
+ Assertions.assertEquals("Error reading data with relations: Foreign key validation failed: [city] -> [name]: 'Munich' not found in resource 'cities'.", dpe.getMessage());
+````
+As we could see, we can read the Datapackage, but if we call `teams.checkRelations(dp)`, there is a foreign key violation. That's because our lookup table `cities` doesn't have a city of `Munich` but we have a team from there. We need to fix it in `cities` resource:
+
+````json
+{
+ "name": "cities",
+ "data": [
+ ["name", "country"],
+ ["London", "England"],
+ ["Madrid", "Spain"],
+ ["Munich", "Germany"]
+ ]
+ }
+````
+
+Now, calling `teams.checkRelations(dp)` will no longer throw an exception.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index cb17a2b..1587d56 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,9 +1,10 @@
-
+
4.0.0
io.frictionlessdata
datapackage-java
- 1.0-SNAPSHOT
+ 0.9.7-SNAPSHOT
jar
https://github.com/frictionlessdata/datapackage-java/issues
@@ -17,24 +18,29 @@
UTF-8
- 1.8
- 1.8
- 7cde68ef43
- 1.3
- 5.7.1
- 4.4
- 1.12.2
- 3.8.1
- 3.0.1
- 3.0.1
- 3.1.0
- 2.22.0
- 2.8.2
- 1.6
- 2.5.3
- 1.6.8
+ UTF-8
+ 17
+ ${java.version}
+ ${java.version}
+ ${java.version}
+ 0.9.6
+ 5.13.2
+ 2.0.17
+ 4.5.0
+ 3.14.0
+ 3.8.1
+ 3.3.1
+ 3.11.2
+ 3.3.1
+ 3.5.3
+ 3.1.4
+ 3.0.1
+ 3.1.1
+ 1.7.0
4.3.0
- 0.8.5
+ 12.1.3
+ 0.8.13
+ 4.9.3.2
@@ -53,6 +59,7 @@
utf-8
${maven.compiler.source}
${maven.compiler.target}
+ ${maven.compiler.compiler}
@@ -69,8 +76,7 @@
org.apache.maven.plugins
maven-surefire-plugin
${maven-surefire-plugin.version}
-
-
+
@@ -121,76 +127,68 @@
- org.apache.maven.plugins
- maven-gpg-plugin
- ${maven-gpg-plugin.version}
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
- sign-artifacts
- verify
+ prepare-agent
- sign
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
- org.sonatype.plugins
- nexus-staging-maven-plugin
- ${nexus-staging-maven-plugin.version}
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
+ org.owasp
+ dependency-check-maven
+ ${dependency-check-maven.version}
+
+
+
+
+
+
+
org.apache.maven.plugins
- maven-release-plugin
- ${maven-release-plugin.version}
-
- true
- false
- forked-path
- -Dgpg.passphrase=${gpg.passphrase}
-
-
-
- org.apache.maven.scm
- maven-scm-provider-gitexe
- 1.9.4
-
-
-
-
-
-
- org.eluder.coveralls
- coveralls-maven-plugin
- ${coveralls-maven-plugin.version}
-
-
-
- org.jacoco
- jacoco-maven-plugin
- ${jacoco-maven-plugin.version}
+ maven-dependency-plugin
+ ${maven-dependency-plugin.version}
- prepare-agent
+ analyze-report
+ package
- prepare-agent
+ analyze-report
+
+ ${project.build.directory}/dependency-report
+
- org.owasp
- dependency-check-maven
- 6.0.1
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ ${spotbugs-maven-plugin.version}
+
+ Max
+ High
+ false
+
@@ -210,49 +208,20 @@
-
-
- org.junit.jupiter
- junit-jupiter-engine
- ${junit.version}
- test
-
-
- org.junit.vintage
- junit-vintage-engine
- ${junit.version}
- test
-
-
-
+
org.slf4j
slf4j-simple
- 1.7.30
+ ${slf4j-simple.version}
test
-
-
- org.hamcrest
- hamcrest-all
- ${hamcrest.version}
- test
-
-
-
-
-
- com.github.erosb
- everit-json-schema
- ${everit-json-schema.version}
-
-
+
org.apache.commons
commons-collections4
- ${apache-commons-collections.version}
+ ${apache-commons-collections4.version}
@@ -261,5 +230,14 @@
tableschema-java
${tableschema-java-version}
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
-
\ No newline at end of file
+
diff --git a/src/main/java/io/frictionlessdata/datapackage/BaseInterface.java b/src/main/java/io/frictionlessdata/datapackage/BaseInterface.java
new file mode 100644
index 0000000..710e9c0
--- /dev/null
+++ b/src/main/java/io/frictionlessdata/datapackage/BaseInterface.java
@@ -0,0 +1,108 @@
+package io.frictionlessdata.datapackage;
+
+import java.util.List;
+
+public interface BaseInterface {
+
+ /**
+ * @return the name
+ */
+ String getName();
+
+ /**
+ * @param name the name to set
+ */
+ void setName(String name);
+
+ /**
+ * @return the profile
+ */
+ String getProfile();
+
+ /**
+ * @param profile the profile to set
+ */
+ void setProfile(String profile);
+
+ /**
+ * @return the title
+ */
+ String getTitle();
+
+ /**
+ * @param title the title to set
+ */
+ void setTitle(String title);
+
+ /**
+ * @return the description
+ */
+ String getDescription();
+
+ /**
+ * @param description the description to set
+ */
+ void setDescription(String description);
+
+
+ /**
+ * @return the sources
+ */
+ List getSources();
+
+ /**
+ * @param sources the sources to set
+ */
+ void setSources(List sources);
+
+ /**
+ * @return the licenses
+ */
+ List getLicenses();
+
+ /**
+ * @param licenses the licenses to set
+ */
+ void setLicenses(List licenses);
+
+ /**
+ * @return the encoding
+ */
+ String getEncoding();
+
+ /**
+ * @param encoding the encoding to set
+ */
+ void setEncoding(String encoding);
+
+ /**
+ * @return the bytes
+ */
+ Integer getBytes();
+
+ /**
+ * @param bytes the bytes to set
+ */
+ void setBytes(Integer bytes);
+
+ /**
+ * @return the hash
+ */
+ String getHash();
+
+ /**
+ * @param hash the hash to set
+ */
+ void setHash(String hash);
+
+ /**
+ * @return the mediaType
+ */
+ String getMediaType();
+
+ /**
+ * @param mediaType the mediaType to set
+ */
+ void setMediaType(String mediaType);
+
+}
diff --git a/src/main/java/io/frictionlessdata/datapackage/Contributor.java b/src/main/java/io/frictionlessdata/datapackage/Contributor.java
index d84fa23..5a5c528 100644
--- a/src/main/java/io/frictionlessdata/datapackage/Contributor.java
+++ b/src/main/java/io/frictionlessdata/datapackage/Contributor.java
@@ -1,16 +1,18 @@
package io.frictionlessdata.datapackage;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.exc.InvalidFormatException;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import io.frictionlessdata.datapackage.exceptions.DataPackageException;
import io.frictionlessdata.tableschema.util.JsonUtil;
+import org.apache.commons.lang3.StringUtils;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.*;
-
-import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import com.fasterxml.jackson.databind.exc.InvalidFormatException;
-
-import static io.frictionlessdata.datapackage.Package.isValidUrl;
+import java.util.Collection;
+import java.util.Objects;
@JsonPropertyOrder({
"title",
@@ -24,7 +26,7 @@ public class Contributor {
private String title;
private String email;
private URL path;
- private Role role;
+ private String role;
private String organization;
public String getTitle() {
@@ -39,7 +41,7 @@ public URL getPath() {
return path;
}
- public Role getRole() {
+ public String getRole() {
return role;
}
@@ -47,59 +49,29 @@ public String getOrganization() {
return organization;
}
- /**
- * Create a new Contributor object from a JSON representation
- * @param jsonObj JSON representation, eg. from Package definition
- * @return new Dialect object with values from JSONObject
- */
- public static Contributor fromJson(Map jsonObj) {
- if (null == jsonObj)
- return null;
- try {
- Contributor c = JsonUtil.getInstance().convertValue(jsonObj, Contributor.class);
- if (!isValidUrl(c.path)) {
- throw new DataPackageException(invalidUrlMsg);
- }
- return c;
- } catch (Exception ex) {
- Throwable cause = ex.getCause();
- if (Objects.nonNull(cause) && cause.getClass().isAssignableFrom(InvalidFormatException.class)) {
- if (Objects.nonNull(cause.getCause()) && cause.getCause().getClass().isAssignableFrom(MalformedURLException.class)) {
- throw new DataPackageException(invalidUrlMsg);
- }
- }
- throw new DataPackageException(ex);
- }
- }
-
- /**
- * Create a new Contributor object from a JSON representation
- * @param jsonArr JSON representation, eg. from Package definition
- * @return new Dialect object with values from JSONObject
- */
- public static Collection fromJson(Collection