/**
* JHOVE2 - Next-generation architecture for format-aware characterization
*
* Copyright (c) 2009 by The Regents of the University of California,
* Ithaka Harbors, Inc., and The Board of Trustees of the Leland Stanford
* Junior University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of the University of California/California Digital
* Library, Ithaka Harbors/Portico, or Stanford University, nor the names of
* its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package org.jhove2.app.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.jhove2.core.JHOVE2Exception;
import org.jhove2.core.reportable.info.ReportablePropertyInfo;
/**
* Base class for generating editable Java properties files for features of
* {@link org.jhove2.core.reportable.Reportable} classes (for example, properties
* files for configuring display of {@link org.jhove2.core.reportable.Reportable} properties,
* or units of measure for {@link org.jhove2.core.reportable.Reportable} properties)
*
* @author smorrissey
*
*/
public abstract class PropertyFileGenerator {
/** File extension for JHOVE2 properties files*/
public static final String EXTENSION = ".properties";
/** Boiler plate text for head of JHOVE2 properties files*, specific to each class of file */
protected String headerInfo;
/** Fully-qualified class name for which properties file is to be generated */
protected String className;
/** Key-Value map to be serialized as property file */
protected Map<String, String> prop2Value;
/** Base name for property file */
protected String propertyFileBaseName;
/** Base directory for output file. Intermediate directories corresponding to segments in
* the fully qualified class name will be created as subdirectories of this base directory
* when the property file is created */
protected String baseOutputDirectory;
/** Full path to property file to be created */
protected String fullFilePath;
/** A set of all {@link org.jhove2.core.reportable.info.ReportablePropertyInfo} descriptors of a
* {@link org.jhove2.core.reportable.Reportable} class */
protected Set<ReportablePropertyInfo> propsList;
/** Specifies whether to include properties inherited from interfaces and super-classes */
protected boolean includeAncestors;
/**
* Constructor
*/
public PropertyFileGenerator() {
super();
this.prop2Value = new TreeMap<String, String>();
}
/**
* Method to create actual list of possible property values (may be an empty list,
* as for units properties file)
* @return HashMap<String, String> containing actual list of possible property values
*/
public abstract Map<String, String> createPropertyValues();
/**
* Principal method. Constructs a property file with JHOVE2 identifier as the key,
* and a "|" separated list of possible legal values (may be empty, as with units file)
* @throws JHOVE2Exception
*/
public void createPropertyFile() throws JHOVE2Exception{
PrintStream printer = null;
// get the list of features for the class
this.setPropsList(FeatureConfigurationUtil.
getProperitiesAsReportablePropertyInfoSet(this.getClassName(),getIncludeAncestors()));
// create the property values for each feature
this.setProp2Value(this.createPropertyValues());
// construct the full path name for properties files
String relFilePath = this.constructFileNameFromClassName(this.getClassName());
this.setFullFilePath(this.getBaseOutputDirectory().concat
(relFilePath));
// create any subdirectories needed for the file
this.makeDirs(this.getFullFilePath());
try {
printer =
new PrintStream (new FileOutputStream(this.getFullFilePath()));
} catch (FileNotFoundException e) {
throw new JHOVE2Exception(
"Unable to create output file " + this.getFullFilePath(), e);
}
if (this.getHeaderInfo() != null){
printer.println(this.getHeaderInfo());
}
for (String property:this.getProp2Value().keySet()){
StringBuffer sb = new StringBuffer(property);
sb.append("\t");
String value = this.getProp2Value().get(property);
if (value != null){
sb.append(value);
}
// escape any ":" in string
String formattedString = this.convertToPropsFileString(sb.toString());
printer.println(formattedString);
}
printer.flush();
printer.close();
return;
}
/**
* Utility method to replace instances of ":" with "\:" in JHOVE2 I8R strings
* @param sourceString String to be converted
* @return converted String
*/
public String convertToPropsFileString(String sourceString){
String targetString = sourceString;
if (sourceString != null){
targetString = targetString.replace(":", "\\:");
}
return targetString;
}
/**
* Constructs relative path to properties file that is constructed
* from the dotted notation of the fully-qualified class name
* @param fully-qualified class name
* @return String containing relative path of new property file
*/
public String constructFileNameFromClassName(String className){
StringBuffer relativePath = new StringBuffer();
String separator = System.getProperty("file.separator");
if (!this.getBaseOutputDirectory().endsWith(separator)){
relativePath.append(separator);
}
String classAsPath = className.replace(".", separator);
relativePath.append(classAsPath);
relativePath.append(this.getPropertyFileBaseName());
relativePath.append(EXTENSION);
return relativePath.toString();
}
/**
* Makes any necessary directories from base path to full property file path
* @param full path name of property file
* @throws JHOVE2Exception
*/
public void makeDirs(String fullFilePath) throws JHOVE2Exception{
String dirPath = fullFilePath;
int i = fullFilePath.lastIndexOf(System.getProperty("file.separator"));
if (i>0){
dirPath = fullFilePath.substring(0,i+1);
File dirFile = new File(dirPath);
if (dirFile.exists()){
if (!dirFile.isDirectory()){
throw new JHOVE2Exception(
"Directory path " + dirPath + " exists but is not directory");
}
else if (!dirFile.canWrite()){
throw new JHOVE2Exception(
"Directory path " + dirPath + " exists but is not writable");
}
}// end if file exists
else {
try{
dirFile.mkdirs();
}
catch (SecurityException e){
throw new JHOVE2Exception (
"Exception thrown trying to create directory " + dirPath, e);
}
}// end else if dir does not exist
}// end if file separator charcter found in file name
return;
}
/**
* Accessor for String containing any information to be placed at beginning of properties file
* @return the headerInfo
*/
public String getHeaderInfo() {
return headerInfo;
}
/**
* Mutator for any information to be placed at end of properties file
* @param headerInfo the headerInfo to set
*/
public void setHeaderInfo(String headerInfo) {
this.headerInfo = headerInfo;
}
/**
* Accessor for name of class for which properties file is to be generated
* @return the className
*/
public String getClassName() {
return className;
}
/**
* Mutator for name of class for which properties file is to be generated
* @param className the className to set
*/
public void setClassName(String className) {
this.className = className;
}
/**
* @return the prop2Value
*/
public Map<String, String> getProp2Value() {
return prop2Value;
}
/**
* @param prop2Value the prop2Value to set
*/
public void setProp2Value(Map<String, String> prop2Value) {
this.prop2Value = prop2Value;
}
/**
* @return the propertyFileBaseName
*/
public String getPropertyFileBaseName() {
return propertyFileBaseName;
}
/**
* @param propertyFileBaseName the propertyFileBaseName to set
*/
public void setPropertyFileBaseName(String propertyFileBaseName) {
this.propertyFileBaseName = propertyFileBaseName;
}
/**
* @return the baseOutputDirectory
*/
public String getBaseOutputDirectory() {
return baseOutputDirectory;
}
/**
* @param baseOutputDirectory the baseOutputDirectory to set
*/
public void setBaseOutputDirectory(String baseOutputDirectory) {
this.baseOutputDirectory = baseOutputDirectory;
}
/**
* @return the fullFilePath
*/
public String getFullFilePath() {
return fullFilePath;
}
/**
* @param fullFilePath the fullFilePath to set
*/
public void setFullFilePath(String fullFilePath) {
this.fullFilePath = fullFilePath;
}
/**
* @return the propsList
*/
public Set<ReportablePropertyInfo> getPropsList() {
return propsList;
}
/**
* @param propsList the propsList to set
*/
public void setPropsList(Set<ReportablePropertyInfo> propsList) {
this.propsList = propsList;
}
/**
* @return boolean Specifying whether to include properties inherited from interfaces and super-classes
*/
public boolean getIncludeAncestors() {
return includeAncestors;
}
/**
* @param includeAncestors Specifies whether to include properties inherited from interfaces and super-classes
*/
public void setIncludeAncestors(boolean includeAncestors) {
this.includeAncestors = includeAncestors;
}
}