/*
* PdfFileParam.java
*
* Classes:
* public FileParam
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Java jcmdline (command line management) package.
*
* The Initial Developer of the Original Code is Lynne Lawrence.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Andrea Vacondio <andrea.vacondio@gmail.com>
*
* ***** END LICENSE BLOCK *****
*/
package jcmdline;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import jcmdline.dto.PdfFile;
/**
* Encapsulate a command line parameter whose value will be the name of
* a pdf document amd its password (Ex. file.pdf:pwd). Attributes, such as whether
* it must be readable, etc, may be specified and will be validated.
* <p>
* Usage:
* <pre>
* public static void main(String[] args) {
*
* PdfFileParam filesArg =
* new PdfFileParam("file",
* "a file to be processed - defaults to stdin",
* PdfFileParam.IS_READABLE,
* PdfFileParam.OPTIONAL,
* PdfFileParam.MULTI_VALUED);
*
*
* }
* </pre>
*
* @author Andrea Vacondio
* @version jcmdline Rel. @VERSION@ $Id: PdfFileParam.java
* @see CmdLineParser
*/
public class PdfFileParam extends AbstractParameter {
// Note: attributes are specified with kind of a "reverse map" so
// that they can be "ANDed" together when set, which is more natural
// since that is the way they are processed.
/**
* indicates that no file/dir attributes are required or will be checked
* @see #setAttributes(int) setAttributes()
*/
public static final int NO_ATTRIBUTES = 0xffff;
/**
* indicates that a file specified as a value for this
* PdfFileParam must exist
* @see #setAttributes(int) setAttributes()
*/
public static final int EXISTS = 0xfffe;
/**
* indicates that a value specified for this PdfFileParam must name an
* existing file for which the caller has read access
* @see #setAttributes(int) setAttributes()
*/
public static final int IS_READABLE = 0xffef;
/**
* indicates that a value specified for this PdfFileParam must name an
* existing file for which the caller has write access
* @see #setAttributes(int) setAttributes()
*/
public static final int IS_WRITEABLE = 0xffdf;
/**
* the default label that will represent option values for this Parameter.
* The following demonstrates a possible usage for a PdfFileParam option,
* where the option label is '<file>':
* <pre>
* out <file> the output file
* </pre>
* @see AbstractParameter#setOptionLabel(String) setOptionLabel()
* @see "<i>PdfFileParam.defaultFileOptionLabel</i> in 'strings' properties
* file"
*/
public static final String DEFAULT_FILE_OPTION_LABEL =
Strings.get("PdfFileParam.defaultFileOptionLabel");
/**
* Attributes which a file/directory value must have
* @see #setAttributes(int) setAttributes()
* @see #getAttributes()
*/
private int attributes;
/**
* constructor - creates single-valued, optional, public parameter
* which accepts any valid file name as its value
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @throws IllegalArgumentException if <code>tag</code>
* or <desc> are invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
*/
public PdfFileParam(String tag, String desc) {
this(tag, desc, NO_ATTRIBUTES, OPTIONAL, SINGLE_VALUED, PUBLIC);
}
/**
* constructor - creates single-valued, public parameter which accepts
* any valid file name as its value and is optional or
* required, as specified.
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @param optional {@link Parameter#OPTIONAL OPTIONAL} if
* optional,
* {@link Parameter#REQUIRED REQUIRED} if required
* @throws IllegalArgumentException if any of the specified
* parameters are invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
* @see Parameter#OPTIONAL OPTIONAL
* @see Parameter#REQUIRED REQUIRED
*/
public PdfFileParam(String tag, String desc, boolean optional) {
this(tag, desc, NO_ATTRIBUTES, optional, SINGLE_VALUED, PUBLIC);
}
/**
* constructor - creates a single-valued, optional, public, parameter
* accepts a file name with the specified attributes.
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @param attributes the attributes that must apply to a file or
* directory specified as a value to this FileParam
* @throws IllegalArgumentException if any parameter is
* invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
* @see #setAttributes(int) setAttributes()
*/
public PdfFileParam(String tag, String desc, int attributes) {
this(tag, desc, attributes, OPTIONAL, SINGLE_VALUED, PUBLIC);
}
/**
* constructor - creates a single-valued, public, parameter
* that accepts a file name with the specified attributes,
* and which is required or optional, as specified.
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @param attributes the attributes that must apply to a file or
* directory specified as a value to this FileParam
* @param optional {@link Parameter#OPTIONAL OPTIONAL} if
* optional,
* {@link Parameter#REQUIRED REQUIRED} if required
* @throws IllegalArgumentException if any parameter is
* invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
* @see #setAttributes(int) setAttributes()
* @see Parameter#OPTIONAL OPTIONAL
* @see Parameter#REQUIRED REQUIRED
*/
public PdfFileParam(String tag,
String desc,
int attributes,
boolean optional) {
this(tag, desc, attributes, optional, SINGLE_VALUED, PUBLIC);
}
/**
* constructor - creates a public parameter that accepts a file
* name with the specified attributes, and which is required
* or optional and/or multi-valued, as specified.
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @param attributes the attributes that must apply to a file or
* directory specified as a value to this FileParam
* @param optional {@link Parameter#OPTIONAL OPTIONAL} if
* optional,
* {@link Parameter#REQUIRED REQUIRED} if required
* @param multiValued {@link Parameter#MULTI_VALUED MULTI_VALUED} if
* the parameter can accept multiple values,
* {@link Parameter#SINGLE_VALUED SINGLE_VALUED}
* if the parameter can contain only a single value
* @throws IllegalArgumentException if any parameter is
* invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
* @see #setAttributes(int) setAttributes()
* @see Parameter#OPTIONAL OPTIONAL
* @see Parameter#REQUIRED REQUIRED
* @see Parameter#SINGLE_VALUED SINGLE_VALUED
* @see Parameter#MULTI_VALUED MULTI_VALUED
*/
public PdfFileParam(String tag,
String desc,
int attributes,
boolean optional,
boolean multiValued) {
this(tag, desc, attributes, optional, multiValued, PUBLIC);
}
/**
* constructor - creates a parameter that accepts a file
* name with the specified attributes, and which is required or optional
* and/or multi-valued or hidden, as specified.
* <P>
* If the <code>IS_DIR</code> attribute is specified, the option label for
* this FileParam will be set to {@link #DEFAULT_DIR_OPTION_LABEL},
* else it will be {@link #DEFAULT_FILE_OPTION_LABEL}.
*
* @param tag a unique identifier for this parameter
* @param desc a description of the parameter, suitable for display
* in a usage statement
* @param attributes the attributes that must apply to a file or
* directory specified as a value to this FileParam
* @param optional {@link Parameter#OPTIONAL OPTIONAL} if
* optional,
* {@link Parameter#REQUIRED REQUIRED} if required
* @param multiValued {@link Parameter#MULTI_VALUED MULTI_VALUED} if
* the parameter can accept multiple values,
* {@link Parameter#SINGLE_VALUED SINGLE_VALUED}
* if the parameter can contain only a single value
* @param hidden {@link Parameter#HIDDEN HIDDEN} if parameter is
* not to be listed in the usage,
* {@link Parameter#PUBLIC PUBLIC} otherwise.
* @throws IllegalArgumentException if any parameter is
* invalid.
* @see AbstractParameter#setTag(String) setTag()
* @see AbstractParameter#setDesc(String) setDesc()
* @see AbstractParameter#setOptionLabel(String) setOptionLabel()
* @see #setAttributes(int) setAttributes()
* @see Parameter#OPTIONAL OPTIONAL
* @see Parameter#REQUIRED REQUIRED
* @see Parameter#SINGLE_VALUED SINGLE_VALUED
* @see Parameter#MULTI_VALUED MULTI_VALUED
* @see Parameter#HIDDEN HIDDEN
* @see Parameter#PUBLIC PUBLIC
*/
public PdfFileParam(String tag,
String desc,
int attributes,
boolean optional,
boolean multiValued,
boolean hidden) {
this.setTag(tag);
this.setAttributes(attributes);
this.setDesc(desc);
this.optional = optional;
this.multiValued = multiValued;
this.hidden = hidden;
this.setOptionLabel(DEFAULT_FILE_OPTION_LABEL);
}
/**
* Gets the value of the PdfFileParam as a PdfFileParam object. If the PdfFileParam is
* multi-valued, the first value is returned.
*
* @return the value as a PdfFile object
* @throws RuntimeException if the value of the FileParam
* has not been set.
* @see Parameter#isSet()
*/
public PdfFile getPdfFile() {
PdfFile retVal = null;
if (!set) {
throw new RuntimeException(Strings.get(
"PdfFileParam.valueNotSet", new Object[] { tag }));
}
retVal = getPdfFile((String)values.get(0));
return retVal;
}
/**
* Gets the values of the PdfFileParam as a Collection of PdfFile objects.
* If the PdfFileParam has no values, an empty Collection is returned.
*
* @return a Collection of PdfFile objects, possibly empty
* @see Parameter#isSet()
*/
public Collection getPdfFiles() {
ArrayList vals = new ArrayList(values.size());
for (Iterator itr = values.iterator(); itr.hasNext(); ) {
vals.add(getPdfFile((String)itr.next()));
}
return vals;
}
/**
* Validates a prospective value for the PdfFileParam - called by
* add/setValue(s)(). All of the attributes are validated and the a
* CmdLineException is thrown if any are not satisfied.
*
* @param val the value to validate
* @throws CmdLineException if <code>value</code> is not valid.
* @see #setAttributes(int) setAttributes()
*/
public void validateValue(String val) throws CmdLineException {
super.validateValue(val);
PdfFile f = null;
try {
f = getPdfFile(val);
} catch (Exception e) {
throwIllegalValueException(val);
}
if (attrSpecified(EXISTS) && !f.getFile().exists()) {
throwIllegalValueException(val);
}
if (attrSpecified(IS_READABLE) && !f.getFile().canRead()) {
throwIllegalValueException(val);
}
if (attrSpecified(IS_WRITEABLE) && !f.getFile().canWrite()) {
throwIllegalValueException(val);
}
}
/**
* Indicates whether an attribute has been specified for this FileParam.
*
* @param attr one of {@link #NO_ATTRIBUTES}, {@link #EXISTS},
* {@link #IS_READABLE}, or
* {@link #IS_WRITEABLE}
* @return <code>true</code> if the attribute is set,
* <code>false</code> if the attribute is not set or
* <code>attr</code> is not a valid attribute
*/
public boolean attrSpecified(int attr) {
if (!(attr == EXISTS ||
attr == NO_ATTRIBUTES ||
attr == IS_READABLE ||
attr == IS_WRITEABLE)) {
return false;
}
return (((attributes | attr) ^ 0xffff) != 0);
}
/**
* Sets the value of attributes. Multiple attributes may be specified
* by ANDing them together. If multiple attributes are specified,
* all conditions must be met for a parameter value to be considered
* valid. For example:
* <pre>
* FileParam fp = new FileParam("tempDir",
* "a directory in which temporary files can be stored",
* FileParam.IS_DIR & FileParam.IS_WRITEABLE);
* </pre>
* In this case, a valid parameter value would have to be both a
* directory and writeable.
* <P>
* Specify <code>NO_ATTRIBUTES</code> if none of the other attributes is
* required.
*
* @param attributes a combination of {@link #NO_ATTRIBUTES},
* {@link #EXISTS},
* {@link #IS_READABLE}, and {@link #IS_WRITEABLE}
* @throws IllegalArgumentException if the attributes value
* is invalid.
* @see #getAttributes()
*/
public void setAttributes(int attributes) {
if ((attributes ^ 0xffff) >= ((IS_WRITEABLE ^ 0xffff) * 2)) {
throw new IllegalArgumentException(Strings.get(
"PdfFileParam.invalidAttributes",
new Object[] { new Integer(attributes) }));
}
this.attributes = attributes;
}
/**
* gets the value of attributes
*
* @return The attributes specified for this FileParam
* @see #setAttributes(int) setAttributes()
*/
public int getAttributes() {
return attributes;
}
/**
* Throws a nicely formatted error message when an invalid value is
* attempted to be validated.
*
* @param val the value that failed validation
* @return doesn't - throws a CmdLineException
* @throws CmdLineException - that's its goal!
*/
private void throwIllegalValueException (String val)
throws CmdLineException {
String s1 = Strings.get("FileParam.file");
String s2;
if (attrSpecified(EXISTS) ||
attrSpecified(IS_READABLE) ||
attrSpecified(IS_WRITEABLE)) {
s2 = Strings.get("PdfFileParam.an_existing");
} else {
s2 = Strings.get("PdfFileParam.a");
}
String s3 = "";
if (attrSpecified(IS_READABLE)) {
if (attrSpecified(IS_WRITEABLE)) {
s3 = Strings.get("FileParam.readable_writeable");
} else {
s3 = Strings.get("PdfFileParam.readable");
}
} else if (attrSpecified(IS_WRITEABLE)) {
s3 = Strings.get("PdfFileParam.writeable");
}
throw new CmdLineException(Strings.get(
"PdfFileParam.illegalValue",new Object[] { s2, s1, s3, val, tag }));
}
/**
* @param value
* @return the PdfFile
*/
private PdfFile getPdfFile(String value){
PdfFile retVal = null;
int k = value.toLowerCase().lastIndexOf(".pdf:");
if (k < 0){
retVal = new PdfFile(new File(value),null);
}else{
retVal = new PdfFile(new File(value.substring(0, k+4)),value.substring(k+5, value.length()));
}
return retVal;
}
}