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

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

23 Apr 2025 02:53PM UTC coverage: 86.477% (+0.5%) from 85.989%
#368

Pull #247

github

web-flow
Merge 71e7caa5e into 0ab3f3ca9
Pull Request #247: Generalize reading and writing crates

251 of 278 new or added lines in 16 files covered. (90.29%)

21 existing lines in 5 files now uncovered.

1880 of 2174 relevant lines covered (86.48%)

0.86 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
     *
50
     * Calling this multiple times will add multiple author IDs.
51
     *
52
     * @param id the identifier of the author.
53
     */
54
    public void addAuthorId(String id) {
UNCOV
55
        this.addIdProperty("author", id);
×
UNCOV
56
    }
×
57

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

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

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

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

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

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

117
        /**
118
         * Sets the location of the data entity.
119
         *
120
         * If the ID has not been set manually in beforehand, it will be derived
121
         * from the path. Use {@link #setId(String)} to override it or set it in
122
         * beforehand. Note that another call of {@link #setLocation(Path)} will
123
         * not override the ID as it has been set by the previous call!
124
         *
125
         * @param path the location of the data. May be null, in which case
126
         * nothing happens.
127
         * @return this builder
128
         */
129
        public T setLocation(Path path) {
130
            if (path != null) {
1✔
131
                if (this.getId() == null) {
1✔
132
                    this.setId(path.getFileName().toString());
1✔
133
                }
134
                this.location = path;
1✔
135
            }
136
            return self();
1✔
137
        }
138

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

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

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

185
        public T setLicense(String id) {
186
            this.addIdProperty("license", id);
1✔
187
            return self();
1✔
188
        }
189

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

195
        public T addAuthor(String id) {
196
            this.authors.add(id);
1✔
197
            return self();
1✔
198
        }
199

200
        public T setContentLocation(String id) {
201
            this.addIdProperty("contentLocation", id);
1✔
202
            return self();
1✔
203
        }
204

205
        @Override
206
        public abstract DataEntity build();
207
    }
208

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

218
        @Override
219
        public DataEntityBuilder self() {
220
            return this;
1✔
221
        }
222

223
        @Override
224
        public DataEntity build() {
225
            return new DataEntity(this);
1✔
226
        }
227
    }
228
}
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