/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.businessobject.lookup;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.IOCase;
import org.apache.commons.io.filefilter.AbstractFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.sys.batch.BatchFile;
import org.kuali.kfs.sys.batch.BatchFileUtils;
import org.kuali.kfs.sys.batch.service.BatchFileAdminAuthorizationService;
import org.kuali.kfs.sys.util.KfsDateUtils;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
import org.kuali.rice.kns.lookup.HtmlData;
import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
import org.kuali.rice.kns.web.ui.Field;
import org.kuali.rice.kns.web.ui.Row;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.UrlFactory;
public class BatchFileLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
protected DateTimeService dateTimeService;
protected BatchFileAdminAuthorizationService batchFileAdminAuthorizationService;
@Override
public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
List<BatchFile> results = new ArrayList<BatchFile>();
IOFileFilter filter = FileFilterUtils.fileFileFilter();
IOFileFilter pathBasedFilter = getPathBasedFileFilter();
if (pathBasedFilter != null) {
filter = FileFilterUtils.andFileFilter(filter, pathBasedFilter);
}
String fileNamePattern = fieldValues.get("fileName");
IOFileFilter fileNameBasedFilter = getFileNameBasedFilter(fileNamePattern);
if (fileNameBasedFilter != null) {
filter = FileFilterUtils.andFileFilter(filter, fileNameBasedFilter);
}
String lastModifiedDate = fieldValues.get("lastModifiedDate");
IOFileFilter lastModifiedDateBasedFilter = getLastModifiedDateBasedFilter(lastModifiedDate);
if (lastModifiedDateBasedFilter != null) {
filter = FileFilterUtils.andFileFilter(filter, lastModifiedDateBasedFilter);
}
BatchFileFinder finder = new BatchFileFinder(results, filter);
List<File> rootDirectories = BatchFileUtils.retrieveBatchFileLookupRootDirectories();
finder.find(rootDirectories);
return results;
}
protected IOFileFilter getPathBasedFileFilter() {
List<File> selectedFiles = getSelectedDirectories(getSelectedPaths());
if (selectedFiles.isEmpty()) {
return null;
}
IOFileFilter fileFilter = null;
for (File selectedFile : selectedFiles) {
IOFileFilter subFilter = new SubDirectoryFileFilter(selectedFile);
if (fileFilter == null) {
fileFilter = subFilter;
}
else {
fileFilter = FileFilterUtils.orFileFilter(fileFilter, subFilter);
}
}
return fileFilter;
}
protected IOFileFilter getFileNameBasedFilter(String fileNamePattern) {
if (StringUtils.isNotBlank(fileNamePattern)) {
return new WildcardFileFilter(fileNamePattern, IOCase.INSENSITIVE);
}
return null;
}
protected IOFileFilter getLastModifiedDateBasedFilter(String lastModifiedDatePattern) {
if (StringUtils.isBlank(lastModifiedDatePattern)) {
return null;
}
try {
if (lastModifiedDatePattern.startsWith("<=")) {
String dateString = StringUtils.removeStart(lastModifiedDatePattern, "<=");
Date toDate = dateTimeService.convertToDate(dateString);
return new LastModifiedDateFileFilter(null, toDate);
}
if (lastModifiedDatePattern.startsWith(">=")) {
String dateString = StringUtils.removeStart(lastModifiedDatePattern, ">=");
Date fromDate = dateTimeService.convertToDate(dateString);
return new LastModifiedDateFileFilter(fromDate, null);
}
if (lastModifiedDatePattern.contains("..")) {
String[] dates = StringUtils.splitByWholeSeparator(lastModifiedDatePattern, "..", 2);
Date fromDate = dateTimeService.convertToDate(dates[0]);
Date toDate = dateTimeService.convertToDate(dates[1]);
return new LastModifiedDateFileFilter(fromDate, toDate);
}
}
catch (ParseException e) {
throw new RuntimeException("Can't parse date", e);
}
throw new RuntimeException("Unable to perform search using last modified date " + lastModifiedDatePattern);
}
protected List<File> getSelectedDirectories(String[] selectedPaths) {
List<File> directories = new ArrayList<File>();
if (selectedPaths != null) {
for (String selectedPath : selectedPaths) {
File directory = new File(BatchFileUtils.resolvePathToAbsolutePath(selectedPath));
if (!directory.exists()) {
throw new RuntimeException("Non existent directory " + BatchFileUtils.resolvePathToAbsolutePath(selectedPath));
}
directories.add(directory);
}
}
return directories;
}
/**
* KRAD Conversion: gets rows after customizing the field values
*
* No use of data dictionary
*/
protected String[] getSelectedPaths() {
List<Row> rows = getRows();
if (rows == null) {
return null;
}
for (Row row : rows) {
for (Field field : row.getFields()) {
if ("path".equals(field.getPropertyName()) && Field.MULTISELECT.equals(field.getFieldType())) {
String[] values = field.getPropertyValues();
return values;
}
}
}
return null;
}
protected class SubDirectoryFileFilter extends AbstractFileFilter {
private File superDirectory;
public SubDirectoryFileFilter(File superDirectory) {
this.superDirectory = superDirectory.getAbsoluteFile();
}
@Override
public boolean accept(File file) {
file = file.getAbsoluteFile();
file = file.getParentFile();
while (file != null) {
if (file.equals(superDirectory)) {
return true;
}
file = file.getParentFile();
}
return false;
}
}
protected class LastModifiedDateFileFilter extends AbstractFileFilter {
private Date fromDate;
private Date toDate;
public LastModifiedDateFileFilter(Date fromDate, Date toDate) {
this.fromDate = fromDate;
this.toDate = toDate;
}
@Override
public boolean accept(File file) {
Date lastModifiedDate = KfsDateUtils.clearTimeFields(new Date(file.lastModified()));
if (fromDate != null && fromDate.after(lastModifiedDate)) {
return false;
}
if (toDate != null && toDate.before(lastModifiedDate)) {
return false;
}
return true;
}
}
protected class BatchFileFinder extends DirectoryWalker {
private List<BatchFile> results;
public BatchFileFinder(List<BatchFile> results, IOFileFilter fileFilter) {
super(null, fileFilter, -1);
this.results = results;
}
public void find(Collection<File> rootDirectories) {
try {
for (File rootDirectory : rootDirectories) {
walk(rootDirectory, null);
}
}
catch (IOException e) {
throw new RuntimeException("Error performing lookup", e);
}
}
/**
* @see org.apache.commons.io.DirectoryWalker#handleFile(java.io.File, int, java.util.Collection)
*/
@Override
protected void handleFile(File file, int depth, Collection results) throws IOException {
super.handleFile(file, depth, results);
BatchFile batchFile = new BatchFile();
batchFile.setFile(file);
this.results.add(batchFile);
}
}
public void setDateTimeService(DateTimeService dateTimeService) {
this.dateTimeService = dateTimeService;
}
@Override
public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
List<HtmlData> links = new ArrayList<HtmlData>();
BatchFile batchFile = (BatchFile) businessObject;
if (canDownloadFile(batchFile)) {
links.add(getDownloadUrl(batchFile));
}
if (canDeleteFile(batchFile)) {
links.add(getDeleteUrl(batchFile));
}
return links;
}
protected boolean canDownloadFile(BatchFile batchFile) {
return batchFileAdminAuthorizationService.canDownload(batchFile, GlobalVariables.getUserSession().getPerson());
}
protected boolean canDeleteFile(BatchFile batchFile) {
return batchFileAdminAuthorizationService.canDelete(batchFile, GlobalVariables.getUserSession().getPerson());
}
protected HtmlData getDownloadUrl(BatchFile batchFile) {
Properties parameters = new Properties();
parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath()));
parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "download");
String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters);
return new AnchorHtmlData(href, "download", "Download");
}
protected HtmlData getDeleteUrl(BatchFile batchFile) {
Properties parameters = new Properties();
parameters.put("filePath", BatchFileUtils.pathRelativeToRootDirectory(batchFile.retrieveFile().getAbsolutePath()));
parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, "delete");
String href = UrlFactory.parameterizeUrl("../batchFileAdmin.do", parameters);
return new AnchorHtmlData(href, "delete", "Delete");
}
/**
* @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
*/
@Override
public void validateSearchParameters(Map fieldValues) {
super.validateSearchParameters(fieldValues);
String[] selectedPaths = getSelectedPaths();
if (selectedPaths != null) {
for (String selectedPath : selectedPaths) {
String resolvedPath = BatchFileUtils.resolvePathToAbsolutePath(selectedPath);
if (!BatchFileUtils.isDirectoryAccessible(resolvedPath)) {
throw new RuntimeException("Can't access path " + selectedPath);
}
}
}
}
/**
* Sets the batchFileAdminAuthorizationService attribute value.
* @param batchFileAdminAuthorizationService The batchFileAdminAuthorizationService to set.
*/
public void setBatchFileAdminAuthorizationService(BatchFileAdminAuthorizationService batchFileAdminAuthorizationService) {
this.batchFileAdminAuthorizationService = batchFileAdminAuthorizationService;
}
}