Skip to content

Commit 4d78c2c

Browse files
committed
refactored BagCreator to reuse methods instead of duplicating them
1 parent f2fe534 commit 4d78c2c

File tree

2 files changed

+129
-77
lines changed

2 files changed

+129
-77
lines changed

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

Lines changed: 113 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@
3131
/**
3232
* Responsible for creating a bag in place.
3333
*/
34-
//TODO look at cleaning up this class so we don't have to ignore CPD
34+
@SuppressWarnings("PMD.TooManyMethods")
3535
public final class BagCreator {
3636
private static final Logger logger = LoggerFactory.getLogger(BagCreator.class);
3737
private static final ResourceBundle messages = ResourceBundle.getBundle("MessageBundle");
3838
private static final String DATE_FORMAT = "yyyy-MM-dd";
39+
private static final Version DOT_BAGIT_VERSION = new Version(2, 0);
40+
private static final Version LATEST_NON_DOT_BAGIT_VERSION = new Version(0, 97);
3941

4042
private BagCreator(){}
4143

@@ -47,29 +49,14 @@ private BagCreator(){}
4749
* @param root the directory that will become the base of the bag and where to start searching for content
4850
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
4951
* @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
5152
*
5253
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
5354
* @throws IOException if there is a problem writing or moving file(s)
5455
*
5556
* @return a {@link Bag} object representing the newly created bagit bag
5657
*/
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{
59-
final Bag bag = new Bag(new Version(0, 97));
60-
bag.setRootDir(root);
61-
logger.info(messages.getString("creating_bag"), bag.getVersion(), root);
62-
63-
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;
58+
public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
59+
return bagInPlace(LATEST_NON_DOT_BAGIT_VERSION, root, algorithms, includeHidden, new Metadata());
7360
}
7461

7562
/**
@@ -80,57 +67,34 @@ public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorith
8067
* @param root the directory that will become the base of the bag and where to start searching for content
8168
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
8269
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
70+
* @param metadata the metadata to include when creating the bag. Payload-Oxum and Bagging-Date will be overwritten
8371
*
8472
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
8573
* @throws IOException if there is a problem writing or moving file(s)
8674
*
8775
* @return a {@link Bag} object representing the newly created bagit bag
8876
*/
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{
94-
Files.createDirectory(dataDir);
95-
try(final DirectoryStream<Path> directoryStream = Files.newDirectoryStream(root)){
96-
for(final Path path : directoryStream){
97-
if(!path.equals(dataDir) && (!Files.isHidden(path) || includeHidden)){
98-
Files.move(path, dataDir.resolve(path.getFileName()));
99-
}
100-
}
101-
}
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{
105-
logger.info(messages.getString("creating_payload_manifests"));
106-
final Map<Manifest, MessageDigest> payloadFilesMap = Hasher.createManifestToMessageDigestMap(algorithms);
107-
final CreatePayloadManifestsVistor payloadVisitor = new CreatePayloadManifestsVistor(payloadFilesMap, includeHidden);
108-
Files.walkFileTree(dataDir, payloadVisitor);
109-
110-
bag.getPayLoadManifests().addAll(payloadFilesMap.keySet());
111-
ManifestWriter.writePayloadManifests(bag.getPayLoadManifests(), root, root, bag.getFileEncoding());
112-
113-
logger.info(messages.getString("creating_tag_manifests"));
114-
final Map<Manifest, MessageDigest> tagFilesMap = Hasher.createManifestToMessageDigestMap(algorithms);
115-
final CreateTagManifestsVistor tagVistor = new CreateTagManifestsVistor(tagFilesMap, includeHidden);
116-
Files.walkFileTree(root, tagVistor);
117-
118-
bag.getTagManifests().addAll(tagFilesMap.keySet());
119-
ManifestWriter.writeTagManifests(bag.getTagManifests(), root, root, bag.getFileEncoding());
77+
public static Bag bagInPlace(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden, final Metadata metadata) throws NoSuchAlgorithmException, IOException{
78+
return bagInPlace(LATEST_NON_DOT_BAGIT_VERSION, root, algorithms, includeHidden, metadata);
12079
}
12180

122-
private static void createMetadataFile(final Path root, final Path dataDir, final Bag bag, final Metadata metadata) throws IOException{
123-
bag.setMetadata(metadata);
124-
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());
81+
/**
82+
* Creates a basic(only required elements) .bagit bag in place.
83+
* This creates files and directories, thus if an error is thrown during operation it may leave the filesystem
84+
* in an unknown state of transition. Thus this is <b>not thread safe</b>
85+
*
86+
* @param root the directory that will become the base of the bag and where to start searching for content
87+
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
88+
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
89+
*
90+
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
91+
* @throws IOException if there is a problem writing files or .bagit directory
92+
*
93+
* @return a {@link Bag} object representing the newly created bagit bag
94+
*/
95+
@Incubating
96+
public static Bag createDotBagit(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
97+
return bagInPlace(DOT_BAGIT_VERSION, root, algorithms, includeHidden, new Metadata());
13498
}
13599

136100
/**
@@ -141,39 +105,111 @@ private static void createMetadataFile(final Path root, final Path dataDir, fina
141105
* @param root the directory that will become the base of the bag and where to start searching for content
142106
* @param algorithms an collection of {@link SupportedAlgorithm} implementations
143107
* @param includeHidden to include hidden files when generating the bagit files, like the manifests
108+
* @param metadata the metadata to include when creating the bag. Payload-Oxum and Bagging-Date will be overwritten
144109
*
145110
* @throws NoSuchAlgorithmException if {@link MessageDigest} can't find the algorithm
146111
* @throws IOException if there is a problem writing files or .bagit directory
147112
*
148113
* @return a {@link Bag} object representing the newly created bagit bag
149114
*/
150115
@Incubating
151-
@SuppressWarnings("CPD-END")
152-
public static Bag createDotBagit(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
153-
final Bag bag = new Bag(new Version(2, 0));
154-
bag.setRootDir(root);
116+
public static Bag createDotBagit(final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden, final Metadata metadata) throws NoSuchAlgorithmException, IOException{
117+
return bagInPlace(DOT_BAGIT_VERSION, root, algorithms, includeHidden, metadata);
118+
}
119+
120+
private static Bag bagInPlace(final Version version, final Path root, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden, final Metadata metadata) throws NoSuchAlgorithmException, IOException{
121+
final Bag bag = new Bag(version);
155122
logger.info(messages.getString("creating_bag"), bag.getVersion(), root);
123+
bag.setRootDir(root);
124+
125+
createDirectories(bag);
126+
moveDataFilesIfNeeded(bag, includeHidden);
156127

157-
final Path dotbagitDir = root.resolve(".bagit");
158-
Files.createDirectories(dotbagitDir);
128+
createBagitFile(bag);
129+
130+
createPayloadManifests(bag, algorithms, includeHidden);
159131

132+
createMetadataFile(bag, metadata);
133+
134+
createTagManifests(bag, algorithms, includeHidden);
135+
136+
return bag;
137+
}
138+
139+
//create the data or .bagit directory
140+
private static void createDirectories(final Bag bag) throws IOException{
141+
if(bag.getVersion().isSameOrNewer(DOT_BAGIT_VERSION)){
142+
//create .bagit directory
143+
final Path dotbagitDir = bag.getRootDir().resolve(".bagit");
144+
Files.createDirectories(dotbagitDir);
145+
}
146+
else{
147+
//create data directory
148+
final Path dataDir = bag.getRootDir().resolve("data");
149+
Files.createDirectories(dataDir);
150+
}
151+
}
152+
153+
private static void createBagitFile(final Bag bag) throws IOException{
154+
BagitFileWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), PathUtils.getBagitDir(bag));
155+
}
156+
157+
private static void moveDataFilesIfNeeded(final Bag bag, final boolean includeHidden) throws IOException{
158+
if(bag.getVersion().isOlder(DOT_BAGIT_VERSION)){
159+
final Path dataDir = PathUtils.getDataDir(bag);
160+
try(final DirectoryStream<Path> directoryStream = Files.newDirectoryStream(bag.getRootDir())){
161+
for(final Path path : directoryStream){
162+
if(!path.equals(dataDir) && (!Files.isHidden(path) || includeHidden)){
163+
Files.move(path, dataDir.resolve(path.getFileName()));
164+
}
165+
}
166+
}
167+
}
168+
}
169+
170+
private static Map<Manifest, MessageDigest> calculatePayloadManifests(final Bag bag, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
171+
final Path dataDir = PathUtils.getDataDir(bag);
160172
logger.info(messages.getString("creating_payload_manifests"));
161-
final Map<Manifest, MessageDigest> map = Hasher.createManifestToMessageDigestMap(algorithms);
162-
final CreatePayloadManifestsVistor visitor = new CreatePayloadManifestsVistor(map, includeHidden);
163-
Files.walkFileTree(root, visitor);
173+
final Map<Manifest, MessageDigest> payloadFilesMap = Hasher.createManifestToMessageDigestMap(algorithms);
174+
final CreatePayloadManifestsVistor payloadVisitor = new CreatePayloadManifestsVistor(payloadFilesMap, includeHidden);
175+
Files.walkFileTree(dataDir, payloadVisitor);
164176

165-
bag.getPayLoadManifests().addAll(map.keySet());
166-
BagitFileWriter.writeBagitFile(bag.getVersion(), bag.getFileEncoding(), dotbagitDir);
167-
ManifestWriter.writePayloadManifests(bag.getPayLoadManifests(), dotbagitDir, root, bag.getFileEncoding());
177+
return payloadFilesMap;
178+
}
179+
180+
private static void createPayloadManifests(final Bag bag, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
181+
final Map<Manifest, MessageDigest> payloadFilesMap = calculatePayloadManifests(bag, algorithms, includeHidden);
182+
bag.getPayLoadManifests().addAll(payloadFilesMap.keySet());
183+
ManifestWriter.writePayloadManifests(bag.getPayLoadManifests(), PathUtils.getBagitDir(bag), bag.getRootDir(), bag.getFileEncoding());
184+
}
185+
186+
private static void createMetadataFile(final Bag bag, final Metadata metadata) throws IOException{
187+
bag.setMetadata(metadata);
168188

189+
logger.debug(messages.getString("calculating_payload_oxum"), PathUtils.getDataDir(bag));
190+
final String payloadOxum = PathUtils.generatePayloadOxum(PathUtils.getDataDir(bag));
191+
bag.getMetadata().upsertPayloadOxum(payloadOxum);
192+
193+
bag.getMetadata().remove("Bagging-Date"); //remove the old bagging date if it exists so that there is only one
194+
bag.getMetadata().add("Bagging-Date", new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH).format(new Date()));
195+
196+
logger.info(messages.getString("creating_metadata_file"));
197+
MetadataWriter.writeBagMetadata(bag.getMetadata(), bag.getVersion(), PathUtils.getBagitDir(bag), bag.getFileEncoding());
198+
}
199+
200+
private static Map<Manifest, MessageDigest> calculateTagManifests(final Bag bag, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
169201
logger.info(messages.getString("creating_tag_manifests"));
170202
final Map<Manifest, MessageDigest> tagFilesMap = Hasher.createManifestToMessageDigestMap(algorithms);
171203
final CreateTagManifestsVistor tagVistor = new CreateTagManifestsVistor(tagFilesMap, includeHidden);
172-
Files.walkFileTree(dotbagitDir, tagVistor);
204+
Files.walkFileTree(PathUtils.getBagitDir(bag), tagVistor);
173205

174-
bag.getTagManifests().addAll(tagFilesMap.keySet());
175-
ManifestWriter.writeTagManifests(bag.getTagManifests(), dotbagitDir, root, bag.getFileEncoding());
206+
return tagFilesMap;
207+
}
208+
209+
private static void createTagManifests(final Bag bag, final Collection<SupportedAlgorithm> algorithms, final boolean includeHidden) throws NoSuchAlgorithmException, IOException{
210+
final Map<Manifest, MessageDigest> tagFilesMap = calculateTagManifests(bag, algorithms, includeHidden);
176211

177-
return bag;
212+
bag.getTagManifests().addAll(tagFilesMap.keySet());
213+
ManifestWriter.writeTagManifests(bag.getTagManifests(), PathUtils.getBagitDir(bag), bag.getRootDir(), bag.getFileEncoding());
178214
}
179215
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,22 @@ public static Path getDataDir(final Version version, final Path output){
108108
return output.resolve(PAYLOAD_DIR_NAME);
109109
}
110110

111+
/**
112+
* With bagit version 2.0 (.bagit) bagit specific files are no longer at the bag root directory.
113+
* This method accounts for this and will return the directory that contains the bag specific files.
114+
*
115+
* @param bag the bag
116+
*
117+
* @return the directory which contains the bag specific files, like manifests or bagit.txt
118+
*/
119+
public static Path getBagitDir(final Bag bag){
120+
if(bag.getVersion().isSameOrNewer(new Version(2, 0))){ //is it a .bagit version?
121+
return bag.getRootDir().resolve(DOT_BAGIT_DIR_NAME);
122+
}
123+
124+
return bag.getRootDir();
125+
}
126+
111127
/**
112128
* With bagit version 2.0 (.bagit) bagit specific files are no longer at the bag root directory.
113129
* This method accounts for this and will return the directory that contains the bag specific files.

0 commit comments

Comments
 (0)