55import edu .kit .datamanager .ro_crate .Crate ;
66import edu .kit .datamanager .ro_crate .entities .data .DataEntity ;
77import edu .kit .datamanager .ro_crate .objectmapper .MyObjectMapper ;
8+ import edu .kit .datamanager .ro_crate .preview .CratePreview ;
89import net .lingala .zip4j .ZipFile ;
910import net .lingala .zip4j .model .ZipParameters ;
11+ import org .apache .commons .io .FileUtils ;
1012import org .slf4j .Logger ;
1113import org .slf4j .LoggerFactory ;
1214
1315import java .io .ByteArrayInputStream ;
16+ import java .io .File ;
1417import java .io .IOException ;
1518import java .io .InputStream ;
1619import java .nio .charset .StandardCharsets ;
20+ import java .nio .file .Path ;
21+ import java .util .Optional ;
22+ import java .util .UUID ;
23+ import java .util .regex .Matcher ;
1724
1825/**
1926 * Implementation of the writing strategy to provide a way of writing crates to
2027 * a zip archive.
2128 */
22- public class ZipStrategy implements GenericWriterStrategy <String > {
23-
29+ public class ZipStrategy implements
30+ GenericWriterStrategy <String >,
31+ ElnFormatWriter <String >
32+ {
2433 private static final Logger logger = LoggerFactory .getLogger (ZipStrategy .class );
2534
35+ /**
36+ * Defines if the zip file will directly contain the crate,
37+ * or if it will contain a subdirectory with the crate.
38+ */
39+ protected boolean createRootSubdir = false ;
40+
41+ @ Override
42+ public ElnFormatWriter <String > usingElnStyle () {
43+ this .createRootSubdir = true ;
44+ return this ;
45+ }
46+
2647 @ Override
2748 public void save (Crate crate , String destination ) throws IOException {
49+ String innerFolderName = "" ;
50+ if (this .createRootSubdir ) {
51+ String dot = Matcher .quoteReplacement ("." );
52+ String end = Matcher .quoteReplacement ("$" );
53+ innerFolderName = Path .of (destination ).getFileName ()
54+ .toString ()
55+ // remove .zip or .eln from the end of the file name
56+ // (?i) removes case sensitivity
57+ .replaceFirst ("(?i)" + dot + "zip" + end , "" )
58+ .replaceFirst ("(?i)" + dot + "eln" + end , "" );
59+ if (!innerFolderName .endsWith ("/" )) {
60+ innerFolderName += "/" ;
61+ }
62+ }
2863 try (ZipFile zipFile = new ZipFile (destination )) {
29- saveMetadataJson (crate , zipFile );
30- saveDataEntities (crate , zipFile );
64+ saveMetadataJson (crate , zipFile , innerFolderName );
65+ saveDataEntities (crate , zipFile , innerFolderName );
66+ savePreview (crate , zipFile , innerFolderName );
3167 }
3268 }
3369
34- private void saveDataEntities (Crate crate , ZipFile zipFile ) throws IOException {
70+ private void saveDataEntities (Crate crate , ZipFile zipFile , String prefix ) throws IOException {
3571 for (DataEntity dataEntity : crate .getAllDataEntities ()) {
36- this .saveToZip (dataEntity , zipFile );
72+ this .saveToZip (dataEntity , zipFile , prefix );
3773 }
3874 }
3975
40- private void saveMetadataJson (Crate crate , ZipFile zipFile ) throws IOException {
76+ private void saveMetadataJson (Crate crate , ZipFile zipFile , String prefix ) throws IOException {
4177 // write the metadata.json file
4278 ZipParameters zipParameters = new ZipParameters ();
43- zipParameters .setFileNameInZip ("ro-crate-metadata.json" );
79+ zipParameters .setFileNameInZip (prefix + "ro-crate-metadata.json" );
4480 ObjectMapper objectMapper = MyObjectMapper .getMapper ();
4581 // we create an JsonNode only to have the file written pretty
4682 JsonNode node = objectMapper .readTree (crate .getJsonMetadata ());
@@ -49,25 +85,59 @@ private void saveMetadataJson(Crate crate, ZipFile zipFile) throws IOException {
4985 // write the ro-crate-metadata
5086 zipFile .addStream (inputStream , zipParameters );
5187 }
52- if (crate .getPreview () != null ) {
53- crate .getPreview ().saveAllToZip (zipFile );
88+ }
89+
90+ private void savePreview (Crate crate , ZipFile zipFile , String prefix ) throws IOException {
91+ Optional <CratePreview > preview = Optional .ofNullable (crate .getPreview ());
92+ if (preview .isEmpty ()) {
93+ return ;
94+ }
95+ final String ID = UUID .randomUUID ().toString ();
96+ File tmpPreviewFolder = Path .of ("./.tmp/ro-crate-java/writer-zipStrategy/" )
97+ .resolve (ID )
98+ .toFile ();
99+ FileUtils .forceMkdir (tmpPreviewFolder );
100+ FileUtils .forceDeleteOnExit (tmpPreviewFolder );
101+
102+ preview .get ().generate (crate , tmpPreviewFolder );
103+ String [] paths = tmpPreviewFolder .list ();
104+ if (paths == null ) {
105+ throw new IOException ("No files found in temporary folder" );
106+ }
107+ for (String path : paths ) {
108+ File file = tmpPreviewFolder .toPath ().resolve (path ).toFile ();
109+ if (file .isDirectory ()) {
110+ ZipParameters parameters = new ZipParameters ();
111+ parameters .setRootFolderNameInZip (prefix + path );
112+ parameters .setIncludeRootFolder (false );
113+ zipFile .addFolder (file , parameters );
114+ } else {
115+ ZipParameters zipParameters = new ZipParameters ();
116+ zipParameters .setFileNameInZip (prefix + path );
117+ zipFile .addFile (file , zipParameters );
118+ }
119+ }
120+ try {
121+ FileUtils .forceDelete (tmpPreviewFolder );
122+ } catch (IOException e ) {
123+ logger .error ("Could not delete temporary preview folder: {}" , tmpPreviewFolder );
54124 }
55125 }
56126
57- private void saveToZip (DataEntity entity , ZipFile zipFile ) throws IOException {
127+ private void saveToZip (DataEntity entity , ZipFile zipFile , String prefix ) throws IOException {
58128 if (entity == null || entity .getPath () == null ) {
59129 return ;
60130 }
61131
62132 boolean isDirectory = entity .getPath ().toFile ().isDirectory ();
63133 if (isDirectory ) {
64134 ZipParameters parameters = new ZipParameters ();
65- parameters .setRootFolderNameInZip (entity .getId ());
135+ parameters .setRootFolderNameInZip (prefix + entity .getId ());
66136 parameters .setIncludeRootFolder (false );
67137 zipFile .addFolder (entity .getPath ().toFile (), parameters );
68138 } else {
69139 ZipParameters zipParameters = new ZipParameters ();
70- zipParameters .setFileNameInZip (entity .getId ());
140+ zipParameters .setFileNameInZip (prefix + entity .getId ());
71141 zipFile .addFile (entity .getPath ().toFile (), zipParameters );
72142 }
73143 }
0 commit comments