/*
* File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.formgenerator/src/com/alkacon/opencms/formgenerator/CmsFieldFactory.java,v $
* Date : $Date: 2010/05/21 13:49:19 $
* Version: $Revision: 1.9 $
*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) 2010 Alkacon Software GmbH (http://www.alkacon.com)
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.alkacon.opencms.formgenerator;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.logging.Log;
/**
* A factory to create form field instances of a specified type.<p>
*
* Additional <code>{@link A_CmsField}</code> implementations may be specified in a
* file: "custom_form_field.properties" under "WEB-INF/classes/" of your
* web application. The format has to be as follows:
*
* <pre>
* FIELDS= <fieldtypename>: <fieldtypeclass> [, <fieldtypename>:<fieldtypeclass>]*
* </pre>
*
* where <fieldtypename> is the visible name of the field that will
* be offered in the XML content editor and >fieldtypeclass> has to be
* a fully qualified classame of a class that implemets
* <code>{@link A_CmsField}</code>.
* <p>
*
* @author Thomas Weckert
*
* @version $Revision: 1.9 $
*
* @since 7.0.4
*/
public final class CmsFieldFactory {
/** Filename of the optional custom form field properties. */
public static final String CUSTOM_FORM_FIELD_PROPERTIES = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(
"classes" + File.separatorChar + "custom_form_field.properties");
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsFieldFactory.class);
/** The shared instance of the field factory. */
private static CmsFieldFactory sharedInstance;
/** The registered field types keyed by their type name. */
private Map<String, String> m_registeredFieldTypes;
/**
* Default constructor.<p>
*/
private CmsFieldFactory() {
super();
m_registeredFieldTypes = new HashMap<String, String>(20);
// register all the standard OpenCms field types
registerFieldType(CmsCheckboxField.getStaticType(), CmsCheckboxField.class.getName());
registerFieldType(CmsEmailField.getStaticType(), CmsEmailField.class.getName());
registerFieldType(CmsFileUploadField.getStaticType(), CmsFileUploadField.class.getName());
registerFieldType(CmsHiddenField.getStaticType(), CmsHiddenField.class.getName());
registerFieldType(CmsRadioButtonField.getStaticType(), CmsRadioButtonField.class.getName());
registerFieldType(CmsSelectionField.getStaticType(), CmsSelectionField.class.getName());
registerFieldType(CmsTextField.getStaticType(), CmsTextField.class.getName());
registerFieldType(CmsTextareaField.getStaticType(), CmsTextareaField.class.getName());
registerFieldType(CmsEmptyField.getStaticType(), CmsEmptyField.class.getName());
registerFieldType(CmsPrivacyField.getStaticType(), CmsPrivacyField.class.getName());
registerFieldType(CmsDynamicField.getStaticType(), CmsDynamicField.class.getName());
registerFieldType(CmsTableField.getStaticType(), CmsTableField.class.getName());
registerFieldType(CmsPasswordField.getStaticType(), CmsPasswordField.class.getName());
registerFieldType(CmsPagingField.getStaticType(), CmsPagingField.class.getName());
registerFieldType(CmsDisplayField.getStaticType(), CmsDisplayField.class.getName());
registerFieldType(CmsHiddenDisplayField.getStaticType(), CmsHiddenDisplayField.class.getName());
registerFieldType(CmsParameterField.getStaticType(), CmsParameterField.class.getName());
File propertyFile = null;
try {
// register all custom field types declared in a property file.
// since custom fields are optional, the property file doesn't have to exist necessarily in the file system.
// this file should contain a mapping of field type names to a Java classes separated by a colon ":", e.g.:
// FIELDS=<fieldtype>:<java class>,...,<fieldtype>:<java class>
propertyFile = new File(CUSTOM_FORM_FIELD_PROPERTIES);
if (propertyFile.exists()) {
ExtendedProperties fieldProperties = new ExtendedProperties();
fieldProperties.load(new FileInputStream(propertyFile));
Iterator<String> i = fieldProperties.keySet().iterator();
while (i.hasNext()) {
String key = i.next();
if (!"FIELDS".equalsIgnoreCase(key)) {
continue;
}
String[] values = fieldProperties.getStringArray(key);
if ((values == null) || (values.length == 0)) {
continue;
}
for (int j = 0, n = values.length; j < n; j++) {
String field = values[j];
int index = field.indexOf(":");
if (index == -1) {
continue;
}
String fieldType = field.substring(0, index);
String fieldClass = field.substring(index + 1, field.length());
registerFieldType(fieldType, fieldClass);
}
}
}
} catch (IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error(
Messages.get().getBundle().key(
Messages.LOG_ERR_READING_CUSTOM_FORM_FIELD_PROPERTIES_1,
propertyFile == null ? CUSTOM_FORM_FIELD_PROPERTIES : propertyFile.getAbsolutePath()),
e);
}
}
}
/**
* Returns the shared instance of the field factory.<p>
*
* @return the shared instance of the field factory
*/
public static synchronized CmsFieldFactory getSharedInstance() {
if (sharedInstance == null) {
sharedInstance = new CmsFieldFactory();
}
return sharedInstance;
}
/**
* Returns an instance of a form field of the specified type.<p>
*
* @param type the desired type of the form field
*
* @return the instance of a form field, or null if creating an instance of the class failed
*/
public I_CmsField getField(String type) {
try {
String className = m_registeredFieldTypes.get(type);
return (I_CmsField)Class.forName(className).newInstance();
} catch (Throwable t) {
if (LOG.isWarnEnabled()) {
LOG.warn(Messages.get().getBundle().key(Messages.LOG_ERR_FIELD_INSTANTIATION_1, type), t);
}
}
return null;
}
/**
* @see java.lang.Object#finalize()
*/
@Override
protected void finalize() throws Throwable {
try {
if (m_registeredFieldTypes != null) {
m_registeredFieldTypes.clear();
}
} catch (Throwable t) {
// ignore
}
super.finalize();
}
/**
* Registers a class as a field type in the factory.<p>
*
* @param type the type of the field
* @param className the name of the field class
*
* @return the previous class associated with this type, or null if there was no mapping before
*/
private Object registerFieldType(String type, String className) {
return m_registeredFieldTypes.put(type, className);
}
}