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" )
3535public 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}
0 commit comments