• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kit-data-manager / ro-crate-java / #419

05 May 2025 08:11AM UTC coverage: 90.169% (+0.8%) from 89.357%
#419

Pull #255

github

web-flow
Merge pull request #256 from kit-data-manager/make-spec-examples-executable

Make specification examples (from readme) executable
Pull Request #255: Next Version (v2.1.0-rc2 | v2.1.0)

63 of 70 new or added lines in 16 files covered. (90.0%)

14 existing lines in 5 files now uncovered.

1917 of 2126 relevant lines covered (90.17%)

0.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.67
/src/main/java/edu/kit/datamanager/ro_crate/entities/data/DataEntity.java
1
package edu.kit.datamanager.ro_crate.entities.data;
2

3
import com.fasterxml.jackson.annotation.JsonIgnore;
4

5
import edu.kit.datamanager.ro_crate.entities.AbstractEntity;
6
import edu.kit.datamanager.ro_crate.entities.contextual.ContextualEntity;
7
import static edu.kit.datamanager.ro_crate.special.IdentifierUtils.isUrl;
8
import edu.kit.datamanager.ro_crate.util.ZipUtil;
9

10
import java.io.File;
11
import java.io.IOException;
12
import java.net.URI;
13
import java.nio.file.Path;
14
import java.util.ArrayList;
15
import java.util.List;
16
import net.lingala.zip4j.ZipFile;
17
import net.lingala.zip4j.exception.ZipException;
18
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
19
import net.lingala.zip4j.model.ZipParameters;
20
import org.apache.commons.io.FileUtils;
21

22
/**
23
 * The base class of every data entity.
24
 *
25
 * @author Nikola Tzotchev on 4.2.2022 г.
26
 * @version 1
27
 */
28
public class DataEntity extends AbstractEntity {
29

30
    @JsonIgnore
31
    private Path path;
32

33
    /**
34
     * The constructor that takes an DataEntity builder and instantiates the
35
     * entity.
36
     *
37
     * @param entityBuilder the builder passed as argument.
38
     */
39
    public DataEntity(AbstractDataEntityBuilder<?> entityBuilder) {
40
        super(entityBuilder);
1✔
41
        if (!entityBuilder.authors.isEmpty()) {
1✔
42
            this.addIdListProperties("author", entityBuilder.authors);
1✔
43
        }
44
        this.path = entityBuilder.location;
1✔
45
    }
1✔
46

47
    /**
48
     * Adds an author ID to the entity.
49
     * <p>
50
     * Calling this multiple times will add multiple author IDs.
51
     *
52
     * @param id the identifier of the author.
53
     */
54
    @SuppressWarnings("unused")
55
    public void addAuthorId(String id) {
UNCOV
56
        this.addIdProperty("author", id);
×
UNCOV
57
    }
×
58

59
    /**
60
     * If the data entity contains a physical file. This method will write it
61
     * when the crate is being written to a zip archive.
62
     *
63
     * @param zipFile the zipFile where it should be written.
64
     * @throws ZipException when something goes wrong with the writing to the
65
     * zip file.
66
     */
67
    public void saveToZip(ZipFile zipFile) throws ZipException {
68
        if (this.path != null) {
1✔
69
            ZipParameters zipParameters = new ZipParameters();
1✔
70
            zipParameters.setFileNameInZip(this.getId());
1✔
71
            zipFile.addFile(this.path.toFile(), zipParameters);
1✔
72
        }
73
    }
1✔
74

75
    /**
76
     * If the data entity contains a physical file. This method will write it
77
     * when the crate is being written to a zip archive.
78
     *
79
     * @param zipStream The zip output stream where it should be written.
80
     * @throws ZipException when something goes wrong with the writing to the
81
     * zip file.
82
     * @throws IOException If opening the file input stream fails.
83
     */
84
    public void saveToStream(ZipOutputStream zipStream) throws ZipException, IOException {
85
        if (this.path != null) {
1✔
86
            ZipUtil.addFileToZipStream(zipStream, this.path.toFile(), this.getId());
1✔
87
        }
88
    }
1✔
89

90
    /**
91
     * If the data entity contains a physical file. This method will write it
92
     * when the crate is being written to a folder.
93
     *
94
     * @param file the folder location where the entity should be written.
95
     * @throws IOException if something goes wrong with the writing.
96
     */
97
    public void savetoFile(File file) throws IOException {
98
        if (this.getPath() != null) {
1✔
99
            if (this.getPath().toFile().isDirectory()) {
1✔
100
                FileUtils.copyDirectory(this.getPath().toFile(), file.toPath().resolve(this.getId()).toFile());
1✔
101
            } else {
102
                FileUtils.copyFile(this.getPath().toFile(), file.toPath().resolve(this.getId()).toFile());
1✔
103
            }
104
        }
105
    }
1✔
106

107
    @JsonIgnore
108
    public Path getPath() {
109
        return path;
1✔
110
    }
111

112
    abstract static class AbstractDataEntityBuilder<T extends AbstractDataEntityBuilder<T>> extends
1✔
113
            AbstractEntityBuilder<T> {
114

115
        private Path location;
116
        private List<String> authors = new ArrayList<>();
1✔
117

118
        /**
119
         * Sets the location of the data entity to make a copy from when writing the crate.
120
         * <p>
121
         * Use this if you want to copy the associated file to the crate.
122
         * Do not use it if the file should already be considered (e.g.
123
         * as part of a DataSetEntity).
124
         * <p>
125
         * If the ID has not been set manually in beforehand, it will be derived
126
         * from the path. Use {@link #setId(String)} to override it or set it in
127
         * beforehand. Note that another call of this method will
128
         * not override the ID as it has been set by the previous call!
129
         *
130
         * @param path the location of the data. May be null, in which case
131
         * nothing happens.
132
         * @return this builder
133
         */
134
        public T setLocation(Path path) {
135
            if (path != null) {
1✔
136
                if (this.getId() == null) {
1✔
137
                    this.setId(path.getFileName().toString());
1✔
138
                }
139
                this.location = path;
1✔
140
            }
141
            return self();
1✔
142
        }
143

144
        /**
145
         * A variant of {@link #setLocation(Path)} which may throw exceptions.
146
         *
147
         * @param path the location of the data
148
         * @return this builder
149
         * @throws IllegalArgumentException if path is null
150
         */
151
        public T setLocationWithExceptions(Path path) throws IllegalArgumentException {
152
            if (path == null) {
1✔
UNCOV
153
                throw new IllegalArgumentException("The given path should not be null.");
×
154
            }
155
            return setLocation(path);
1✔
156
        }
157

158
        /**
159
         * Same as {@link #setLocation(Path)} but instead of associating this
160
         * entity with a file, it will point to some place on the internet.
161
         * <p>
162
         * Via the specification, this means the uri will be set as the ID. This
163
         * call is therefore equivalent to {@link #setId(String)}.
164
         *
165
         * @param uri the URI, should point at the data reachable on the
166
         * internet.
167
         * @return this builder
168
         */
169
        public T setLocation(URI uri) {
170
            if (uri != null && this.getId() == null) {
1✔
171
                this.setId(uri.toString());
1✔
172
            }
173
            return self();
1✔
174
        }
175

176
        /**
177
         * A variant of {@link #setLocation(URI)} which may throw exceptions.
178
         *
179
         * @param uri the given uri
180
         * @return this builder
181
         * @throws IllegalArgumentException if uri is null or not a valid URL
182
         */
183
        public T setLocationWithExceptions(URI uri) throws IllegalArgumentException {
184
            if (!isUrl(uri.toString())) {
1✔
185
                throw new IllegalArgumentException("This Data Entity remote ID does not resolve to a valid URL.");
1✔
186
            }
UNCOV
187
            return setLocation(uri);
×
188
        }
189

190
        public T setLicense(String id) {
191
            this.addIdProperty("license", id);
1✔
192
            return self();
1✔
193
        }
194

195
        public T setLicense(ContextualEntity license) {
196
            this.addIdProperty("license", license.getId());
1✔
197
            return self();
1✔
198
        }
199

200
        public T addAuthor(String id) {
201
            this.authors.add(id);
1✔
202
            return self();
1✔
203
        }
204

205
        public T setContentLocation(String id) {
206
            this.addIdProperty("contentLocation", id);
1✔
207
            return self();
1✔
208
        }
209

210
        @Override
211
        public abstract DataEntity build();
212
    }
213

214
    /**
215
     * Data Entity builder class that allows for easier data entity creation.
216
     * <p>
217
     * If not explicitly mentioned, all methods avoid Exceptions and will
218
     * silently ignore null-parameters, in which case nothing will happen. Use
219
     * the available *WithExceptions-methods in case you need them.
220
     */
221
    public static final class DataEntityBuilder extends AbstractDataEntityBuilder<DataEntityBuilder> {
1✔
222

223
        @Override
224
        public DataEntityBuilder self() {
225
            return this;
1✔
226
        }
227

228
        @Override
229
        public DataEntity build() {
230
            return new DataEntity(this);
1✔
231
        }
232
    }
233
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc