/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ejb.plugins.cmp.jdbc.metadata;
import org.jboss.deployment.DeploymentException;
import org.jboss.metadata.MetaData;
import org.jboss.logging.Logger;
import org.w3c.dom.Element;
/**
* Optimistick locking metadata
*
* @author <a href="mailto:aloubyansky@hotmail.com">Alex Loubyansky</a>
* @version $Revision: 81030 $
*/
public final class JDBCOptimisticLockingMetaData
{
// Constants ---------------------------------------
public static final Integer FIELD_GROUP_STRATEGY = new Integer(1);
public static final Integer MODIFIED_STRATEGY = new Integer(2);
public static final Integer READ_STRATEGY = new Integer(4);
public static final Integer VERSION_COLUMN_STRATEGY = new Integer(8);
public static final Integer TIMESTAMP_COLUMN_STRATEGY = new Integer(16);
public static final Integer KEYGENERATOR_COLUMN_STRATEGY = new Integer(32);
// Attributes --------------------------------------
/** locking strategy */
final private Integer lockingStrategy;
/** group name for field group strategy */
final private String groupName;
/** locking field for verion- or timestamp-column strategy */
final private JDBCCMPFieldMetaData lockingField;
/** key generator factory */
final private String keyGeneratorFactory;
/** logger */
final private Logger log;
// Constructors ------------------------------------
/**
* Constructs optimistic locking metadata reading
* optimistic-locking XML element
*/
public JDBCOptimisticLockingMetaData(JDBCEntityMetaData entityMetaData,
Element element)
throws DeploymentException
{
log = Logger.getLogger(entityMetaData.getName());
Element strategyEl;
if((strategyEl = MetaData.getOptionalChild(element, "group-name")) != null)
{
lockingStrategy = FIELD_GROUP_STRATEGY;
groupName = MetaData.getElementContent(strategyEl);
lockingField = null;
keyGeneratorFactory = null;
log.debug("optimistic locking: group=" + groupName);
}
else if((strategyEl = MetaData.getOptionalChild(element, "modified-strategy")) != null)
{
lockingStrategy = MODIFIED_STRATEGY;
groupName = null;
lockingField = null;
keyGeneratorFactory = null;
log.debug("optimistic locking: modified strategy");
}
else if((strategyEl = MetaData.getOptionalChild(element, "read-strategy")) != null)
{
lockingStrategy = READ_STRATEGY;
groupName = null;
lockingField = null;
keyGeneratorFactory = null;
log.debug("optimistic locking: read strategy");
}
else if((strategyEl = MetaData.getOptionalChild(element, "version-column")) != null)
{
String fieldType = MetaData.getOptionalChildContent(element, "field-type");
if(fieldType != null)
throw new DeploymentException(
"field-type is not allowed for version column. It is implicitly set to java.lang.Long."
);
lockingStrategy = VERSION_COLUMN_STRATEGY;
lockingField = constructLockingField(entityMetaData, element);
groupName = null;
keyGeneratorFactory = null;
log.debug("optimistic locking: version-column=" + lockingField.getFieldName());
}
else if((strategyEl = MetaData.getOptionalChild(element, "timestamp-column")) != null)
{
String fieldType = MetaData.getOptionalChildContent(element, "field-type");
if(fieldType != null)
throw new DeploymentException(
"field-type is not allowed for timestamp column. It is implicitly set to java.util.Date."
);
lockingStrategy = TIMESTAMP_COLUMN_STRATEGY;
lockingField = constructLockingField(entityMetaData, element);
groupName = null;
keyGeneratorFactory = null;
log.debug("optimistic locking: timestamp-column=" + lockingField.getFieldName());
}
else if((keyGeneratorFactory =
MetaData.getOptionalChildContent(element, "key-generator-factory")) != null)
{
lockingStrategy = KEYGENERATOR_COLUMN_STRATEGY;
lockingField = constructLockingField(entityMetaData, element);
groupName = null;
log.debug("optimistic locking: key-generator-factory=" + keyGeneratorFactory);
}
else
{
throw new DeploymentException("Unexpected error: entity "
+ entityMetaData.getName()
+ " has unkown/incorrect optimistic locking configuration.");
}
}
// Public ------------------------------------------
public Integer getLockingStrategy()
{
return lockingStrategy;
}
public String getGroupName()
{
return groupName;
}
public JDBCCMPFieldMetaData getLockingField()
{
return lockingField;
}
public String getKeyGeneratorFactory()
{
return keyGeneratorFactory;
}
// Private -----------------------------------------
/**
* Constructs a locking field metadata from
* XML element
*/
private JDBCCMPFieldMetaData constructLockingField(
JDBCEntityMetaData entity,
Element element)
throws DeploymentException
{
// field name
String fieldName = MetaData.getOptionalChildContent(element, "field-name");
if(fieldName == null || fieldName.trim().length() < 1)
fieldName = (lockingStrategy == VERSION_COLUMN_STRATEGY ? "version_lock" :
(lockingStrategy == TIMESTAMP_COLUMN_STRATEGY ? "timestamp_lock" : "generated_lock"));
// column name
String columnName = MetaData.getOptionalChildContent(element, "column-name");
if(columnName == null || columnName.trim().length() < 1)
columnName = (lockingStrategy == VERSION_COLUMN_STRATEGY ? "version_lock" :
(lockingStrategy == TIMESTAMP_COLUMN_STRATEGY ? "timestamp_lock" : "generated_lock"));
// field type
Class fieldType = null;
if(lockingStrategy == VERSION_COLUMN_STRATEGY)
fieldType = java.lang.Long.class;
else if(lockingStrategy == TIMESTAMP_COLUMN_STRATEGY)
fieldType = java.util.Date.class;
String fieldTypeStr = MetaData.getOptionalChildContent(element, "field-type");
if(fieldTypeStr != null)
{
try
{
fieldType = GetTCLAction.
getContextClassLoader().loadClass(fieldTypeStr);
}
catch(ClassNotFoundException e)
{
throw new DeploymentException(
"Could not load field type for optimistic locking field "
+ fieldName + ": " + fieldTypeStr);
}
}
// JDBC/SQL Type
int jdbcType;
String sqlType;
String jdbcTypeName = MetaData.getOptionalChildContent(element, "jdbc-type");
if(jdbcTypeName != null)
{
jdbcType = JDBCMappingMetaData.getJdbcTypeFromName(jdbcTypeName);
sqlType = MetaData.getUniqueChildContent(element, "sql-type");
}
else
{
jdbcType = Integer.MIN_VALUE;
sqlType = null;
}
return new JDBCCMPFieldMetaData(
entity, fieldName, fieldType, columnName, jdbcType, sqlType
);
}
}