/*
* Created on 02-Apr-2007
* Copyright (C) 2007 by Andrea Vacondio.
*
*
* This library is provided under dual licenses.
* You may choose the terms of the Lesser General Public License version 2.1 or the General Public License version 2
* License at your discretion.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation;
* either version 2 of the License.
*
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.pdfsam.console.utils.perfix;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pdfsam.console.exceptions.console.ConsoleException;
/**
* Used to parse the prefix and generate the output filename.
* If the prefix doesn't contain "[CURRENTPAGE]" or "[TIMESTAMP]" it generates oldstyle file name (Ex. 005_prefixFileName.pdf.
* If it contains "[CURRENTPAGE]", "[TIMESTAMP]" or [FILENUMBER] and depending on the generateFileName method you call, it performs variable substitution. (Ex. [BASENAME]_prefix_[CURRENTPAGE] generates FileName_prefix_005.pdf)
* Available variables: [CURRENTPAGE], [TIMESTAMP], [BASENAME], [FILENUMBER]. [CURRENTPAGE] and [FILENUMBER] accept the notation [FILENUMBER####] to specify the output pattern (Ex if the prefix is [FILENUMBER####] and file number is 5 the resulting prefix will be 0005)
* @author a.vacondio
*
*/
public class PrefixParser {
private static final int SIMPLE_PREFIX = 0x00;
private static final int CURRENT_PAGE = 0x01;
private static final int TIMESTAMP = 0x02;
private static final int BASENAME = 0x04;
private static final int FILE_NUMBER = 0x08;
private static final int BOOKMARK_NAME = 0x10;
private static final String PDF_EXTENSION = ".pdf";
//regexp to match
private static final String CURRENT_PAGE_REGX = "(.)*(\\[CURRENTPAGE(#*)\\])+(.)*";
private static final String FILE_NUMBER_REGX = "(.)*(\\[FILENUMBER(#*)(\\d*)\\])+(.)*";
private static final String TIMESTAMP_STRING = "[TIMESTAMP]";
private static final String BASENAME_STRING = "[BASENAME]";
private static final String BOOKMARK_NAME_STRING = "[BOOKMARK_NAME]";
//regexp to replace
private static final String CURRENT_PAGE_REPLACE_REGX = "\\[CURRENTPAGE(#+)*\\]";
private static final String FILE_NUMBER_REPLACE_REGX = "\\[FILENUMBER(#+)*(\\d+)*\\]";
private static final String TIMESTAMP_REPLACE_RGX = "\\[TIMESTAMP\\]";
private static final String BASENAME_REPLACE_REGX = "\\[BASENAME\\]";
private static final String BOOKMARK_NAME_REPLACE_REGX = "\\[BOOKMARK_NAME\\]";
private static final String INVALID_WIN_FILENAME_CHARS_REGEXP = "[\\\\/:*?\\\"<>|]";
private String prefix = "";
private String fileName = "";
private int currentPrefixType = SIMPLE_PREFIX;
/**
*
* @param prefix prefix to use. (Can be empty)
* @param fileName Original file name
* @throws ConsoleException if the original fileName in empty or null
*/
public PrefixParser(String prefix, String fileName) throws ConsoleException{
if (prefix != null){
this.prefix = prefix;
if(prefix.indexOf(TIMESTAMP_STRING) > -1){
currentPrefixType |= TIMESTAMP;
}
if(prefix.indexOf(BASENAME_STRING) > -1){
currentPrefixType |= BASENAME;
}
if(prefix.indexOf(BOOKMARK_NAME_STRING) > -1){
currentPrefixType |= BOOKMARK_NAME;
}
if(prefix.matches(CURRENT_PAGE_REGX)){
currentPrefixType |= CURRENT_PAGE;
}
if(prefix.matches(FILE_NUMBER_REGX)){
currentPrefixType |= FILE_NUMBER;
}
}
if(fileName != null && fileName.length() > 0){
//check if the filename contains '.' and it's at least in second position (Ex. a.pdf)
if(fileName.lastIndexOf('.') > 1){
this.fileName = fileName.substring(0, fileName.lastIndexOf('.'));
}else{
this.fileName = fileName;
}
}else{
throw new ConsoleException(ConsoleException.EMPTY_FILENAME);
}
}
/**
* Generates the filename depending on the type of prefix. If it contains "[CURRENTPAGE]","[TIMESTAMP]","[BOOKMARK_NAME]" or "[FILENUMBER]" it performs variable substitution.
* @param request input parameter
* @return filename generated
*/
public String generateFileName(FileNameRequest request){
String retVal = "";
if(request != null && !request.isEmpty()){
if(isComplexPrefix(request)){
retVal = generateSimpleFileName(true);
if((currentPrefixType & BOOKMARK_NAME)==BOOKMARK_NAME && (request.getBookmarkName()!=null) && (request.getBookmarkName().length()>0)){
retVal = applyBookmarkname(retVal, request.getBookmarkName());
}
if((currentPrefixType & CURRENT_PAGE)==CURRENT_PAGE && request.getPageNumber()!=null){
retVal = applyPagenumber(retVal, request.getPageNumber());
}
if((currentPrefixType & FILE_NUMBER)==FILE_NUMBER && request.getFileNumber()!=null){
retVal = applyFilenumber(retVal, request.getFileNumber());
}
}else{
retVal = generateSimpleFileName(fileName, false);
if(request.getPageNumber()!=null){
retVal = getFileNumberFormatter(request.getPageNumber()).format(request.getPageNumber().intValue())+"_"+retVal;
}
}
}else{
retVal = generateSimpleFileName(fileName, isComplexPrefix());
}
return applyExtension(retVal);
}
/**
* Generates the filename depending on the type of prefix. If it contains "[TIMESTAMP]" or "[BASENAME]" it performs variable substitution.
* @return filename generated
*/
public String generateFileName(){
return generateFileName(new FileNameRequest());
}
/**
* If it contains "[CURRENTPAGE]" and request.getPageNumber()!=null or it contains "[TIMESTAMP]" or it contains "[BOOKMARK_NAME]" and
* request.getBookmarkName()!=null or it contains "[FILENUMBER]" and request.getFileNumber()!=null it's a complex prefix.
* @param request
* @return true if it's a complex prefix
*/
private boolean isComplexPrefix(FileNameRequest request){
boolean retVal = false;
retVal =
((currentPrefixType & BOOKMARK_NAME)==BOOKMARK_NAME && (request.getBookmarkName()!=null) && (request.getBookmarkName().length()>0))
||
((currentPrefixType & CURRENT_PAGE)==CURRENT_PAGE && request.getPageNumber()!=null)
||
((currentPrefixType & FILE_NUMBER)==FILE_NUMBER && request.getFileNumber()!=null)
||
isComplexPrefix();
return retVal;
}
/**
*
* @return true if the prefix contains "[TIMESTAMP]"
*/
private boolean isComplexPrefix(){
return ((currentPrefixType & TIMESTAMP)==TIMESTAMP);
}
/**
* Generates the filename depending on the type of prefix.
* If performSubstitution is true it performs variable substitution replacing [TIMESTAMP] and [BASENAME] when necessary, if not the returned value
* is prefix+defaultPosponedName
* @param defaultPostponedName
* @param performSubstitution if true perform substitution
* @return filename generated
*/
private String generateSimpleFileName(String defaultPostponedName, boolean performSubstitution){
String retVal = prefix;
if(performSubstitution){
if((currentPrefixType & TIMESTAMP)==TIMESTAMP){
retVal = applyTimestamp(retVal);
}
if((currentPrefixType & BASENAME)==BASENAME){
retVal = applyFilename(retVal, fileName);
}
}else{
retVal += defaultPostponedName;
}
return retVal;
}
/**
* Generates the filename depending on the type of prefix.
* If performSubstitution is true it performs variable substitution replacing [TIMESTAMP] and [BASENAME] when necessary, if not the returned value
* is {@link PrefixParser#prefix}
* @param performSubstitution if true perform substitution
* @return filename generated
*/
private String generateSimpleFileName(boolean performSubstitution){
return generateSimpleFileName("", performSubstitution);
}
/**
* Applies the PDF extension to the input string
* @param arg0
* @return
*/
private String applyExtension(String arg0){
String retVal = arg0;
if(arg0!=null && !arg0.endsWith(PDF_EXTENSION)){
retVal += PDF_EXTENSION;
}
return retVal;
}
/**
* Apply FILE_NUMBER_REGX variable substitution to the input argument
* @param arg0
* @param pageNumber
* @return
*/
private String applyFilenumber(String arg0, Integer fileNumber){
String retVal = arg0;
if(fileNumber!=null){
String numberPatter = "";
String startingValue = "";
Matcher m = Pattern.compile(FILE_NUMBER_REGX).matcher(arg0);
if(m.matches()){
numberPatter = m.group(3);
startingValue = m.group(4);
}
int fileNum = 0;
//user entered a starting number
if(startingValue!=null && startingValue.length()>0){
fileNum = Integer.parseInt(startingValue);
}
fileNum += fileNumber.intValue();
String replacement = "";
if(numberPatter!=null && numberPatter.length()>0){
replacement = getFileNumberFormatter(numberPatter).format(fileNum);
}else{
replacement = getFileNumberFormatter(fileNum).format(fileNum);
}
retVal = arg0.replaceAll(FILE_NUMBER_REPLACE_REGX, replacement);
}
return retVal;
}
/**
* Apply CURRENT_PAGE_REPLACE_REGX variable substitution to the input argument
* @param arg0
* @param pageNumber
* @return
*/
private String applyPagenumber(String arg0, Integer pageNumber){
String retVal = arg0;
if(pageNumber!=null){
String numberPatter = "";
Matcher m = Pattern.compile(CURRENT_PAGE_REGX).matcher(arg0);
if(m.matches()){
numberPatter = m.group(3);
}
String replacement = "";
if(numberPatter!=null && numberPatter.length()>0){
replacement = getFileNumberFormatter(numberPatter).format(pageNumber.intValue());
}else{
replacement = getFileNumberFormatter(pageNumber.intValue()).format(pageNumber.intValue());
}
retVal = arg0.replaceAll(CURRENT_PAGE_REPLACE_REGX, replacement);
}
return retVal;
}
/**
* Apply BOOKMARK_NAME_REPLACE_REGX variable substitution to the input argument. Some Win32 invalid chars are stripped by the bookmark name.
* @param arg0
* @param bookmarkName
* @return
*/
private String applyBookmarkname(String arg0, String bookmarkName){
String retVal = arg0;
if(bookmarkName!=null){
//fix #2789961
bookmarkName = bookmarkName.replaceAll(INVALID_WIN_FILENAME_CHARS_REGEXP, "");
retVal = arg0.replaceAll(BOOKMARK_NAME_REPLACE_REGX, bookmarkName);
}
return retVal;
}
/**
* Apply BASENAME_REPLACE_REGX variable substitution to the input argument
* @param arg0
* @param fileName
* @return
*/
private String applyFilename(String arg0, String fileName){
String retVal = arg0;
if(fileName!=null){
retVal = arg0.replaceAll(BASENAME_REPLACE_REGX, fileName);
}
return retVal;
}
/**
* Apply TIMESTAMP_REPLACE_RGX variable substitution to the input argument
* @param arg0
* @return
*/
private String applyTimestamp(String arg0){
String retVal = arg0;
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmssSS").format(new Date());
retVal = retVal.replaceAll(TIMESTAMP_REPLACE_RGX, timestamp);
return retVal;
}
/**
* @param n numbero of pages
* @return
*/
private DecimalFormat getFileNumberFormatter(Integer n){
DecimalFormat retVal = null;
if(n!=null){
retVal = getFileNumberFormatter(n.intValue());
}else{
retVal = new DecimalFormat();
retVal.applyPattern("00000");
}
return retVal;
}
/**
* @param n number of pages
* @return the DecimalFormat
*/
private DecimalFormat getFileNumberFormatter(int n){
DecimalFormat retVal = new DecimalFormat();
try {
retVal.applyPattern(Integer.toString(n).replaceAll("\\d", "0"));
} catch (Exception fe) {
retVal.applyPattern("00000");
}
return retVal;
}
/**
* @param arg0 the input string of the type "####"
* @return
*/
private DecimalFormat getFileNumberFormatter(String arg0){
DecimalFormat retVal = new DecimalFormat();
try {
if(arg0!=null && arg0.length()>0){
retVal.applyPattern(arg0.replaceAll("#", "0"));
}else{
retVal.applyPattern("00000");
}
} catch (Exception fe) {
retVal.applyPattern("00000");
}
return retVal;
}
}