Skip to content

Commit f2fe534

Browse files
committed
refs #93 - added method for inputting your own metadata when bagging in place, and defaults to include date bagged and payload-oxum
1 parent b23b6d5 commit f2fe534

File tree

4 files changed

+87
-30
lines changed

4 files changed

+87
-30
lines changed

src/main/java/gov/loc/repository/bagit/creator/BagCreator.java

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
import java.nio.file.Path;
77
import java.security.MessageDigest;
88
import java.security.NoSuchAlgorithmException;
9+
import java.text.SimpleDateFormat;
910
import java.util.Collection;
11+
import java.util.Date;
12+
import java.util.Locale;
1013
import java.util.Map;
1114
import java.util.ResourceBundle;
1215

@@ -16,40 +19,78 @@
1619
import gov.loc.repository.bagit.annotation.Incubating;
1720
import gov.loc.repository.bagit.domain.Bag;
1821
import gov.loc.repository.bagit.domain.Manifest;
22+
import gov.loc.repository.bagit.domain.Metadata;
1923
import gov.loc.repository.bagit.domain.Version;
2024
import gov.loc.repository.bagit.hash.Hasher;
2125
import gov.loc.repository.bagit.hash.SupportedAlgorithm;
26+
import gov.loc.repository.bagit.util.PathUtils;
2227
import gov.loc.repository.bagit.writer.BagitFileWriter;
2328
import gov.loc.repository.bagit.writer.ManifestWriter;
29+
import gov.loc.repository.bagit.writer.MetadataWriter;
2430

2531
/**
2632
* Responsible for creating a bag in place.
2733
*/
34+
//TODO look at cleaning up this class so we don't have to ignore CPD
2835
public final class BagCreator {
2936
private static final Logger logger = LoggerFactory.getLogger(BagCreator.class);
3037
private static final ResourceBundle messages = ResourceBundle.getBundle("MessageBundle");
38+
private static final String DATE_FORMAT = "yyyy-MM-dd";
3139

3240
private BagCreator(){}
3341

34-
@SuppressWarnings("CPD-START")
3542
/**
36-
* Creates a basic(only required elements) bag in place for version 0.97.
43+
* Creates a bag in place for version 0.97.
3744
* This method moves and creates files, thus if an error is thrown during operation it may leave the filesystem
3845
* in an unknown state of transition. Thus this is <b>not thread safe</b>
3946
*
4047
* @param root the directory that will become the base of the bag and where to start searching for content
4148
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
4249
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
50+
* @param metadata the metadata to include when creating the bag. Payload-Oxum and Bagging-Date will be overwritten
51+
*
4352
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
4453
* @throws IOException if there is a problem writing or moving file(s)
54+
*
4555
* @return a {@link Bag} object representing the newly created bagit bag
4656
*/
47-
public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
57+
@SuppressWarnings("CPD-START")
58+
public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden, final Metadata metadata) throws NoSuchAlgorithmException, IOException{
4859
final Bag bag = new Bag(new Version(0, 97));
4960
bag.setRootDir(root);
5061
logger.info(messages.getString("creating_bag"), bag.getVersion(), root);
5162

5263
final Path dataDir = root.resolve("data");
64+
moveFilesToDataDirectory(root, dataDir, includeHidden);
65+
66+
BagitFileWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), root);
67+
68+
createManifests(root, dataDir, bag, algorithms, includeHidden);
69+
70+
createMetadataFile(root, dataDir, bag, metadata);
71+
72+
return bag;
73+
}
74+
75+
/**
76+
* Creates a bag in place for version 0.97.
77+
* This method moves and creates files, thus if an error is thrown during operation it may leave the filesystem
78+
* in an unknown state of transition. Thus this is <b>not thread safe</b>
79+
*
80+
* @param root the directory that will become the base of the bag and where to start searching for content
81+
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
82+
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
83+
*
84+
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
85+
* @throws IOException if there is a problem writing or moving file(s)
86+
*
87+
* @return a {@link Bag} object representing the newly created bagit bag
88+
*/
89+
public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
90+
return bagInPlace(root, algorithms, includeHidden, new Metadata());
91+
}
92+
93+
private static void moveFilesToDataDirectory(final Path root, final Path dataDir, final boolean includeHidden) throws IOException{
5394
Files.createDirectory(dataDir);
5495
try(final DirectoryStream<Path> directoryStream = Files.newDirectoryStream(root)){
5596
for(final Path path : directoryStream){
@@ -58,14 +99,15 @@ public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorith
5899
}
59100
}
60101
}
61-
102+
}
103+
104+
private static void createManifests(final Path root, final Path dataDir, final Bag bag, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws IOException, NoSuchAlgorithmException{
62105
logger.info(messages.getString("creating_payload_manifests"));
63106
final Map<Manifest, MessageDigest> payloadFilesMap = Hasher.createManifestToMessageDigestMap(algorithms);
64107
final CreatePayloadManifestsVistor payloadVisitor = new CreatePayloadManifestsVistor(payloadFilesMap, includeHidden);
65108
Files.walkFileTree(dataDir, payloadVisitor);
66109

67110
bag.getPayLoadManifests().addAll(payloadFilesMap.keySet());
68-
BagitFileWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), root);
69111
ManifestWriter.writePayloadManifests(bag.getPayLoadManifests(), root, root, bag.getFileEncoding());
70112

71113
logger.info(messages.getString("creating_tag_manifests"));
@@ -75,11 +117,22 @@ public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorith
75117

76118
bag.getTagManifests().addAll(tagFilesMap.keySet());
77119
ManifestWriter.writeTagManifests(bag.getTagManifests(), root, root, bag.getFileEncoding());
120+
}
121+
122+
private static void createMetadataFile(final Path root, final Path dataDir, final Bag bag, final Metadata metadata) throws IOException{
123+
bag.setMetadata(metadata);
78124

79-
return bag;
125+
logger.debug(messages.getString("calculating_payload_oxum"), dataDir);
126+
final String payloadOxum = PathUtils.generatePayloadOxum(PathUtils.getDataDir(bag.getVersion(), root));
127+
bag.getMetadata().upsertPayloadOxum(payloadOxum);
128+
129+
bag.getMetadata().remove("Bagging-Date");
130+
bag.getMetadata().add("Bagging-Date", new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH).format(new Date()));
131+
132+
logger.info(messages.getString("creating_metadata_file"));
133+
MetadataWriter.writeBagMetadata(bag.getMetadata(), bag.getVersion(), root, bag.getFileEncoding());
80134
}
81135

82-
@SuppressWarnings("CPD-END")
83136
/**
84137
* Creates a basic(only required elements) .bagit bag in place.
85138
* This creates files and directories, thus if an error is thrown during operation it may leave the filesystem
@@ -88,11 +141,14 @@ public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorith
88141
* @param root the directory that will become the base of the bag and where to start searching for content
89142
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
90143
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
91-
* @return a {@link Bag} object representing the newly created bagit bag
144+
*
92145
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
93146
* @throws IOException if there is a problem writing files or .bagit directory
147+
*
148+
* @return a {@link Bag} object representing the newly created bagit bag
94149
*/
95150
@Incubating
151+
@SuppressWarnings("CPD-END")
96152
public static Bag createDotBagit(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
97153
final Bag bag = new Bag(new Version(2, 0));
98154
bag.setRootDir(root);
@@ -120,5 +176,4 @@ public static Bag createDotBagit(final Path root, final Collection<SupportedAlgo
120176

121177
return bag;
122178
}
123-
124-
}
179+
}

src/main/java/gov/loc/repository/bagit/util/PathUtils.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import gov.loc.repository.bagit.domain.Bag;
99
import gov.loc.repository.bagit.domain.Version;
10+
import gov.loc.repository.bagit.verify.FileCountAndTotalSizeVistor;
1011

1112
/**
1213
* Convenience class for dealing with various path issues
@@ -123,4 +124,21 @@ public static Path getBagitDir(final Version version, final Path bagRoot){
123124

124125
return bagRoot;
125126
}
127+
128+
/**
129+
* Calculate the total file and byte count of the files in the payload directory
130+
*
131+
* @param dataDir the directory to calculate the payload-oxum
132+
*
133+
* @return the string representation of the payload-oxum value
134+
*
135+
* @throws IOException if there is an error reading any of the files
136+
*/
137+
public static String generatePayloadOxum(final Path dataDir) throws IOException{
138+
final FileCountAndTotalSizeVistor visitor = new FileCountAndTotalSizeVistor();
139+
140+
Files.walkFileTree(dataDir, visitor);
141+
142+
return visitor.getTotalSize() + "." + visitor.getCount();
143+
}
126144
}

src/main/java/gov/loc/repository/bagit/writer/BagWriter.java

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import java.security.MessageDigest;
77
import java.security.NoSuchAlgorithmException;
88
import java.util.HashSet;
9-
import java.util.ResourceBundle;
109
import java.util.Map.Entry;
10+
import java.util.ResourceBundle;
1111
import java.util.Set;
1212

1313
import org.slf4j.Logger;
@@ -17,7 +17,6 @@
1717
import gov.loc.repository.bagit.domain.Manifest;
1818
import gov.loc.repository.bagit.hash.Hasher;
1919
import gov.loc.repository.bagit.util.PathUtils;
20-
import gov.loc.repository.bagit.verify.FileCountAndTotalSizeVistor;
2120

2221
/**
2322
* responsible for writing out a {@link Bag}
@@ -47,7 +46,7 @@ public static void write(final Bag bag, final Path outputDir) throws IOException
4746
final Path bagitDir = PayloadWriter.writeVersionDependentPayloadFiles(bag, outputDir);
4847

4948
logger.debug(messages.getString("upsert_payload_oxum"));
50-
final String payloadOxum = generatePayloadOxum(PathUtils.getDataDir(bag.getVersion(), outputDir));
49+
final String payloadOxum = PathUtils.generatePayloadOxum(PathUtils.getDataDir(bag.getVersion(), outputDir));
5150
bag.getMetadata().upsertPayloadOxum(payloadOxum);
5251

5352
logger.debug(messages.getString("writing_bagit_file"));
@@ -73,23 +72,6 @@ public static void write(final Bag bag, final Path outputDir) throws IOException
7372
}
7473
}
7574

76-
/**
77-
* Calculate the total file and byte count of the files in the payload directory
78-
*
79-
* @param dataDir the directory to calculate the payload-oxum
80-
*
81-
* @return the string representation of the payload-oxum value
82-
*
83-
* @throws IOException if there is an error reading any of the files
84-
*/
85-
private static String generatePayloadOxum(final Path dataDir) throws IOException{
86-
final FileCountAndTotalSizeVistor visitor = new FileCountAndTotalSizeVistor();
87-
88-
Files.walkFileTree(dataDir, visitor);
89-
90-
return visitor.getTotalSize() + "." + visitor.getCount();
91-
}
92-
9375
/*
9476
* Update the tag manifest cause the checksum of the other tag files will have changed since we just wrote them out to disk
9577
*/

src/main/resources/MessageBundle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ skipping_ignored_directory=Skipping [{}] since we are ignoring hidden directorie
9595
creating_bag=Creating a bag with version: [{}] in directory: [{}].
9696
creating_payload_manifests=Creating payload manifest(s).
9797
creating_tag_manifests=Creating tag manifest(s).
98+
calculating_payload_oxum=Calculating the payload oxum of the data directory [{}].
99+
creating_metadata_file=Creating the bag metadata file (bag-info.txt or package-info.txt).
98100

99101
#for Hasher.java
100102
adding_checksum=Adding [{}] to manifest with hash [{}].

0 commit comments

Comments
 (0)