001/* 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.migration.foxml; 017 018import java.io.File; 019import java.io.FileFilter; 020import java.io.FileNotFoundException; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Iterator; 024import java.util.List; 025import java.util.Stack; 026 027import javax.xml.stream.XMLStreamException; 028 029import org.fcrepo.migration.FedoraObjectProcessor; 030 031/** 032 * A depth-first-search iteration over a tree of files that exposes them as FedoraObjectProcessors. 033 * Each file in the tree is expected to be a FOXML file. This implementation likely minimizes 034 * memory usage for the expected organization of FOXML files on disk. 035 * @author mdurbin 036 */ 037public class FoxmlDirectoryDFSIterator implements Iterator<FedoraObjectProcessor> { 038 039 private List<File> current; 040 private Stack<List<File>> stack; 041 042 private InternalIDResolver resolver; 043 private URLFetcher fetcher; 044 045 private String localFedoraServer; 046 047 private FileFilter fileFilter; 048 049 /** 050 * foxml directory DFS iterator. 051 * @param root the root file 052 * @param fetcher the fetcher 053 * @param localFedoraServer uri to local fedora server 054 * @param fileFilter a FileFilter that defined which files should be included 055 * in this Iterator. 056 */ 057 public FoxmlDirectoryDFSIterator(final File root, final URLFetcher fetcher, final String localFedoraServer, 058 final FileFilter fileFilter) { 059 stack = new Stack<List<File>>(); 060 current = new ArrayList<File>(Arrays.asList(root.listFiles())); 061 this.fetcher = fetcher; 062 this.localFedoraServer = localFedoraServer; 063 this.fileFilter = fileFilter; 064 } 065 066 /** 067 * foxml directory DFS iterator with three parameters 068 * @param root the root file 069 * @param resolver the resolver 070 * @param fetcher the fetcher 071 * @param localFedoraServer the domain and port for the server that hosted the fedora objects in the format 072 * "localhost:8080". 073 * @param fileFilter a FileFilter that defined which files should be included 074 * in this Iterator. 075 */ 076 public FoxmlDirectoryDFSIterator(final File root, final InternalIDResolver resolver, final URLFetcher fetcher, 077 final String localFedoraServer, final FileFilter fileFilter) { 078 this(root, fetcher, localFedoraServer, fileFilter); 079 this.resolver = resolver; 080 } 081 082 private boolean advanceToNext() { 083 while (current.size() > 0 || stack.size() > 0) { 084 if (current.isEmpty()) { 085 current = stack.pop(); 086 } else { 087 final File first = current.get(0); 088 if (first.isFile()) { 089 if (this.fileFilter.accept(first)) { 090 return true; 091 } else { 092 // exclude the current file and get the next one... 093 current.remove(0); 094 return advanceToNext(); 095 } 096 } else { 097 final File directory = current.remove(0); 098 stack.push(current); 099 current = new ArrayList<File>(Arrays.asList(directory.listFiles())); 100 } 101 } 102 } 103 return false; 104 } 105 106 @Override 107 public boolean hasNext() { 108 return advanceToNext(); 109 } 110 111 @Override 112 public FedoraObjectProcessor next() { 113 if (!advanceToNext()) { 114 throw new IllegalStateException(); 115 } else { 116 final File currentFile = current.remove(0); 117 try { 118 return new FoxmlInputStreamFedoraObjectProcessor( 119 currentFile, fetcher, resolver, localFedoraServer); 120 } catch (final XMLStreamException e) { 121 throw new RuntimeException(currentFile.getPath() + " doesn't appear to be an XML file." 122 + (e.getMessage() != null ? " (" + e.getMessage() + ")" : "")); 123 } catch (final FileNotFoundException e) { 124 throw new RuntimeException(e); 125 } 126 } 127 } 128 129 @Override 130 public void remove() { 131 throw new UnsupportedOperationException(); 132 } 133 134}