Further DAO for audit values

- General-purpose property persisting in searchable schema
 - TODO: More high volume tests for general values


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@15556 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-08-03 17:59:05 +00:00
parent 8d90b426dc
commit 686ec6479b
13 changed files with 1337 additions and 38 deletions

View File

@@ -45,7 +45,12 @@
<bean id="propertyValueDAO" class="org.alfresco.repo.domain.propval.ibatis.PropertyValueDAOImpl">
<property name="sqlMapClientTemplate" ref="propertyValueSqlMapClientTemplate"/>
<property name="converter">
<bean class="org.alfresco.repo.domain.propval.DefaultPropertyTypeConverter"/>
</property>
<property name="propertyClassCache" ref="immutableEntityCache"/>
<property name="propertyStringValueCache" ref="immutableEntityCache"/>
<property name="propertyDoubleValueCache" ref="immutableEntityCache"/>
</bean>
</beans>

View File

@@ -13,8 +13,16 @@ CREATE TABLE alf_prop_class
java_class_name VARCHAR(255) NOT NULL,
java_class_name_short VARCHAR(32) NOT NULL,
java_class_name_crc BIGINT NOT NULL,
UNIQUE INDEX idx_prop_class_crc (java_class_name_crc, java_class_name_short),
INDEX idx_prop_class_class (java_class_name),
UNIQUE INDEX idx_alf_prop_class_crc (java_class_name_crc, java_class_name_short),
INDEX idx_alf_prop_class_class (java_class_name),
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE alf_prop_double_value
(
id BIGINT NOT NULL AUTO_INCREMENT,
double_value DOUBLE NOT NULL,
INDEX idx_alf_prop_dbl_val (double_value),
PRIMARY KEY (id)
) ENGINE=InnoDB;
@@ -22,19 +30,25 @@ CREATE TABLE alf_prop_string_value
(
id BIGINT NOT NULL AUTO_INCREMENT,
string_value text NOT NULL,
INDEX idx_prop_str_val (string_value(64)),
INDEX idx_alf_prop_str_val (string_value(64)),
PRIMARY KEY (id)
) ENGINE=InnoDB;
--CREATE TABLE alf_prop_string_value
--(
-- id BIGINT NOT NULL AUTO_INCREMENT,
-- string_value text NOT NULL,
-- prop_class_id BIGINT NOT NULL,
-- INDEX idx_prop_str_val (string_value(64)),
-- CONSTRAINT fk_prop_str_classid FOREIGN KEY (prop_class_id) REFERENCES alf_prop_class (id),
-- PRIMARY KEY (id)
--) ENGINE=InnoDB;
CREATE TABLE alf_prop_serializable_value
(
id BIGINT NOT NULL AUTO_INCREMENT,
serializable_value BLOB NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE alf_prop_value
(
id BIGINT NOT NULL AUTO_INCREMENT,
persisted_type TINYINT NOT NULL,
long_value BIGINT NOT NULL,
INDEX idx_alf_prop_val (persisted_type, long_value),
PRIMARY KEY (id)
) ENGINE=InnoDB;
--
-- Record script finish

View File

@@ -12,6 +12,8 @@
<typeAlias alias="PropertyClass" type="org.alfresco.repo.domain.propval.PropertyClassEntity"/>
<typeAlias alias="PropertyStringValue" type="org.alfresco.repo.domain.propval.PropertyStringValueEntity"/>
<typeAlias alias="PropertyDoubleValue" type="org.alfresco.repo.domain.propval.PropertyDoubleValueEntity"/>
<typeAlias alias="PropertyValue" type="org.alfresco.repo.domain.propval.PropertyValueEntity"/>
<!-- -->
<!-- Result Maps -->
@@ -27,6 +29,14 @@
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="stringValue" column="string_value" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>
<resultMap id="result.PropertyDoubleValue" class="PropertyDoubleValue">
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="doubleValue" column="double_value" jdbcType="DOUBLE" javaType="java.lang.Double"/>
</resultMap>
<resultMap id="result.PropertyValue" class="PropertyValue">
<result property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<result property="longValue" column="long_value" jdbcType="BIGINT" javaType="java.lang.Long"/>
</resultMap>
<!-- -->
<!-- Parameter Maps -->
@@ -56,6 +66,16 @@
values (#stringValue#)
</sql>
<sql id="insert.PropertyDoubleValue.AutoIncrement">
insert into alf_prop_double_value (double_value)
values (#doubleValue#)
</sql>
<sql id="insert.PropertyValue.AutoIncrement">
insert into alf_prop_value (persisted_type, long_value)
values (#persistedType#, #longValue#)
</sql>
<!-- -->
<!-- Statements -->
<!-- -->
@@ -101,4 +121,24 @@
string_value = #stringValue#
</select>
<!-- Get a property simple value by ID -->
<select id="select.PropertyDoubleValueByID" parameterClass="PropertyDoubleValue" resultMap="result.PropertyDoubleValue">
select
*
from
alf_prop_double_value
where
id = #id#
</select>
<!-- Get the property string value by string -->
<select id="select.PropertyDoubleValueByValue" parameterClass="PropertyDoubleValue" resultMap="result.PropertyDoubleValue">
select
*
from
alf_prop_double_value
where
double_value = #doubleValue#
</select>
</sqlMap>

View File

@@ -20,4 +20,18 @@
</selectKey>
</insert>
<insert id="insert.PropertyDoubleValue" parameterClass="PropertyDoubleValue" >
<include refid="insert.PropertyDoubleValue.AutoIncrement"/>
<selectKey resultClass="long" keyProperty="id" type="post">
KEY_COLUMN:GENERATED_KEY
</selectKey>
</insert>
<insert id="insert.PropertyValue" parameterClass="PropertyValue" >
<include refid="insert.PropertyValue.AutoIncrement"/>
<selectKey resultClass="long" keyProperty="id" type="post">
KEY_COLUMN:GENERATED_KEY
</selectKey>
</insert>
</sqlMap>

View File

@@ -8,5 +8,5 @@
<sqlMap resource="alfresco/ibatis/#resource.dialect#/propval-common-SqlMap.xml"/>
<sqlMap resource="alfresco/ibatis/#resource.dialect#/propval-insert-SqlMap.xml"/>
</sqlMapConfig>

View File

@@ -31,6 +31,7 @@ import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.cache.lookup.EntityLookupCache;
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAO;
import org.alfresco.repo.domain.CrcHelper;
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
import org.alfresco.util.Pair;
/**
@@ -46,9 +47,15 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
{
private static final String CACHE_REGION_PROPERTY_CLASS = "PropertyClass";
private static final String CACHE_REGION_PROPERTY_STRING_VALUE = "PropertyStringValue";
private static final String CACHE_REGION_PROPERTY_DOUBLE_VALUE = "PropertyDoubleValue";
private static final String CACHE_REGION_PROPERTY_VALUE = "PropertyValue";
protected PropertyTypeConverter converter;
private final PropertyClassCallbackDAO propertyClassDaoCallback;
private final PropertyStringValueCallbackDAO propertyStringValueCallback;
private final PropertyDoubleValueCallbackDAO propertyDoubleValueCallback;
private final PropertyValueCallbackDAO propertyValueCallback;
/**
* Cache for the property class:<br/>
* KEY: ID<br/>
@@ -63,6 +70,20 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
* VALUE KEY: Short string-crc pair ({@link CrcHelper#getStringCrcPair(String, int, boolean, boolean)})<br/>
*/
private EntityLookupCache<Long, String, Pair<String, Long>> propertyStringValueCache;
/**
* Cache for the property double value:<br/>
* KEY: ID<br/>
* VALUE: The Double instance<br/>
* VALUE KEY: The value itself<br/>
*/
private EntityLookupCache<Long, Double, Double> propertyDoubleValueCache;
/**
* Cache for the property value:<br/>
* KEY: ID<br/>
* VALUE: The Serializable instance<br/>
* VALUE KEY: A value key based on the persisted type<br/>
*/
private EntityLookupCache<Long, Serializable, Serializable> propertyValueCache;
/**
* Default constructor.
@@ -74,11 +95,23 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
{
this.propertyClassDaoCallback = new PropertyClassCallbackDAO();
this.propertyStringValueCallback = new PropertyStringValueCallbackDAO();
this.propertyDoubleValueCallback = new PropertyDoubleValueCallbackDAO();
this.propertyValueCallback = new PropertyValueCallbackDAO();
this.propertyClassCache = new EntityLookupCache<Long, Class<?>, String>(propertyClassDaoCallback);
this.propertyStringValueCache = new EntityLookupCache<Long, String, Pair<String, Long>>(propertyStringValueCallback);
this.propertyDoubleValueCache = new EntityLookupCache<Long, Double, Double>(propertyDoubleValueCallback);
this.propertyValueCache = new EntityLookupCache<Long, Serializable, Serializable>(propertyValueCallback);
}
/**
* @param converter the converter that translates between external and persisted values
*/
public void setConverter(PropertyTypeConverter converter)
{
this.converter = converter;
}
/**
* Set the cache to use for <b>alf_prop_class</b> lookups (optional).
*
@@ -105,12 +138,42 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
propertyStringValueCallback);
}
/**
* Set the cache to use for <b>alf_prop_double_value</b> lookups (optional).
*
* @param propertyDoubleValueCache the cache of IDs to property values
*/
public void setPropertyDoubleValueCache(SimpleCache<Serializable, Object> propertyDoubleValueCache)
{
this.propertyDoubleValueCache = new EntityLookupCache<Long, Double, Double>(
propertyDoubleValueCache,
CACHE_REGION_PROPERTY_DOUBLE_VALUE,
propertyDoubleValueCallback);
}
/**
* Set the cache to use for <b>alf_prop_value</b> lookups (optional).
*
* @param propertyValueCache the cache of IDs to property values
*/
public void setPropertyValueCache(SimpleCache<Serializable, Object> propertyValueCache)
{
this.propertyValueCache = new EntityLookupCache<Long, Serializable, Serializable>(
propertyValueCache,
CACHE_REGION_PROPERTY_VALUE,
propertyValueCallback);
}
//================================
// 'alf_prop_class' accessors
//================================
public Pair<Long, Class<?>> getPropertyClass(Long id)
public Pair<Long, Class<?>> getPropertyClassById(Long id)
{
if (id == null)
{
throw new IllegalArgumentException("Cannot look up entity by null ID.");
}
Pair<Long, Class<?>> entityPair = propertyClassCache.getByKey(id);
if (entityPair == null)
{
@@ -121,12 +184,20 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
public Pair<Long, Class<?>> getPropertyClass(Class<?> value)
{
if (value == null)
{
throw new IllegalArgumentException("Property class cannot be null");
}
Pair<Long, Class<?>> entityPair = propertyClassCache.getByValue(value);
return entityPair;
}
public Pair<Long, Class<?>> getOrCreatePropertyClass(Class<?> value)
{
if (value == null)
{
throw new IllegalArgumentException("Property class cannot be null");
}
Pair<Long, Class<?>> entityPair = propertyClassCache.getOrCreateByValue(value);
return entityPair;
}
@@ -136,15 +207,15 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
*/
private class PropertyClassCallbackDAO implements EntityLookupCallbackDAO<Long, Class<?>, String>
{
private final Pair<Long, Class<?>> convertEntityToPair(PropertyClassEntity propertyClassEntity)
private final Pair<Long, Class<?>> convertEntityToPair(PropertyClassEntity entity)
{
if (propertyClassEntity == null)
if (entity == null)
{
return null;
}
else
{
return propertyClassEntity.getEntityPair();
return entity.getEntityPair();
}
}
@@ -180,24 +251,36 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
// 'alf_prop_string_value' accessors
//================================
public Pair<Long, String> getPropertyStringValue(Long id)
public Pair<Long, String> getPropertyStringValueById(Long id)
{
if (id == null)
{
throw new IllegalArgumentException("Cannot look up entity by null ID.");
}
Pair<Long, String> entityPair = propertyStringValueCache.getByKey(id);
if (entityPair == null)
{
throw new AlfrescoRuntimeException("No property class exists for ID " + id);
throw new AlfrescoRuntimeException("No property string value exists for ID " + id);
}
return entityPair;
}
public Pair<Long, String> getPropertyStringValue(String value)
{
if (value == null)
{
throw new IllegalArgumentException("Persisted string values cannot be null");
}
Pair<Long, String> entityPair = propertyStringValueCache.getByValue(value);
return entityPair;
}
public Pair<Long, String> getOrCreatePropertyStringValue(String value)
{
if (value == null)
{
throw new IllegalArgumentException("Persisted string values cannot be null");
}
Pair<Long, String> entityPair = propertyStringValueCache.getOrCreateByValue(value);
return entityPair;
}
@@ -207,15 +290,15 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
*/
private class PropertyStringValueCallbackDAO implements EntityLookupCallbackDAO<Long, String, Pair<String, Long>>
{
private final Pair<Long, String> convertEntityToPair(PropertyStringValueEntity propertyStringValueEntity)
private final Pair<Long, String> convertEntityToPair(PropertyStringValueEntity entity)
{
if (propertyStringValueEntity == null)
if (entity == null)
{
return null;
}
else
{
return propertyStringValueEntity.getEntityPair();
return entity.getEntityPair();
}
}
@@ -247,4 +330,185 @@ public abstract class AbstractPropertyValueDAOImpl implements PropertyValueDAO
protected abstract PropertyStringValueEntity findStringValueByValue(String value);
protected abstract PropertyStringValueEntity createStringValue(String value);
//================================
// 'alf_prop_double_value' accessors
//================================
public Pair<Long, Double> getPropertyDoubleValueById(Long id)
{
if (id == null)
{
throw new IllegalArgumentException("Cannot look up entity by null ID.");
}
Pair<Long, Double> entityPair = propertyDoubleValueCache.getByKey(id);
if (entityPair == null)
{
throw new AlfrescoRuntimeException("No property double value exists for ID " + id);
}
return entityPair;
}
public Pair<Long, Double> getPropertyDoubleValue(Double value)
{
if (value == null)
{
throw new IllegalArgumentException("Persisted double values cannot be null");
}
Pair<Long, Double> entityPair = propertyDoubleValueCache.getByValue(value);
return entityPair;
}
public Pair<Long, Double> getOrCreatePropertyDoubleValue(Double value)
{
if (value == null)
{
throw new IllegalArgumentException("Persisted double values cannot be null");
}
Pair<Long, Double> entityPair = propertyDoubleValueCache.getOrCreateByValue(value);
return (Pair<Long, Double>) entityPair;
}
/**
* Callback for <b>alf_prop_double_value</b> DAO.
*/
private class PropertyDoubleValueCallbackDAO implements EntityLookupCallbackDAO<Long, Double, Double>
{
private final Pair<Long, Double> convertEntityToPair(PropertyDoubleValueEntity entity)
{
if (entity == null)
{
return null;
}
else
{
return entity.getEntityPair();
}
}
public Double getValueKey(Double value)
{
return value;
}
public Pair<Long, Double> createValue(Double value)
{
PropertyDoubleValueEntity entity = createDoubleValue(value);
return convertEntityToPair(entity);
}
public Pair<Long, Double> findByKey(Long key)
{
PropertyDoubleValueEntity entity = findDoubleValueById(key);
return convertEntityToPair(entity);
}
public Pair<Long, Double> findByValue(Double value)
{
PropertyDoubleValueEntity entity = findDoubleValueByValue(value);
return convertEntityToPair(entity);
}
}
protected abstract PropertyDoubleValueEntity findDoubleValueById(Long id);
protected abstract PropertyDoubleValueEntity findDoubleValueByValue(Double value);
protected abstract PropertyDoubleValueEntity createDoubleValue(Double value);
//================================
// 'alf_prop_value' accessors
//================================
public Pair<Long, Serializable> getPropertyValueById(Long id)
{
if (id == null)
{
throw new IllegalArgumentException("Cannot look up entity by null ID.");
}
Pair<Long, Serializable> entityPair = propertyValueCache.getByKey(id);
if (entityPair == null)
{
throw new AlfrescoRuntimeException("No property value exists for ID " + id);
}
return entityPair;
}
public Pair<Long, Serializable> getPropertyValue(Serializable value)
{
Pair<Long, Serializable> entityPair = propertyValueCache.getByValue(value);
return entityPair;
}
public Pair<Long, Serializable> getOrCreatePropertyValue(Serializable value)
{
Pair<Long, Serializable> entityPair = propertyValueCache.getOrCreateByValue(value);
return (Pair<Long, Serializable>) entityPair;
}
/**
* Callback for <b>alf_prop_value</b> DAO.
*/
private class PropertyValueCallbackDAO implements EntityLookupCallbackDAO<Long, Serializable, Serializable>
{
private final Pair<Long, Serializable> convertEntityToPair(PropertyValueEntity entity)
{
if (entity == null)
{
return null;
}
else
{
return entity.getEntityPair();
}
}
public Serializable getValueKey(Serializable value)
{
// Find out how it would be persisted
Pair<Short, Serializable> persistedValuePair = converter.convertToPersistedType(value);
// We don't return keys for pure Serializable instances
if (persistedValuePair.getFirst().equals(PersistedType.SERIALIZABLE.getOrdinalNumber()))
{
// It will be Serialized, so no key
return null;
}
else if (value instanceof String)
{
return CrcHelper.getStringCrcPair((String)value, 128, true, true);
}
else
{
// We've dodged Serializable and String; everything else is OK as a key.
return persistedValuePair;
}
}
public Pair<Long, Serializable> createValue(Serializable value)
{
PropertyValueEntity entity = createPropertyValue(value);
return convertEntityToPair(entity);
}
public Pair<Long, Serializable> findByKey(Long key)
{
PropertyValueEntity entity = findPropertyValueById(key);
return convertEntityToPair(entity);
}
public Pair<Long, Serializable> findByValue(Serializable value)
{
// // Find out how it would be persisted
// Pair<Short, Serializable> persistedValuePair = converter.convertToPersistedType(value);
// // We don't do lookups for serializable values
// if (persistedValuePair.getFirst().equals(PersistedType.SERIALIZABLE.getOrdinalNumber()))
// {
// // It will be Serialized, so no we don't look it up
// return null;
// }
PropertyValueEntity entity = findPropertyValueByValue(value);
return convertEntityToPair(entity);
}
}
protected abstract PropertyValueEntity findPropertyValueById(Long id);
protected abstract PropertyValueEntity findPropertyValueByValue(Serializable value);
protected abstract PropertyValueEntity createPropertyValue(Serializable value);
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* 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, or (at your option) any later version.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import java.io.Serializable;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Default converter for handling data going to and from the persistence layer.
* <p>
* This implementation uses an explicit mapping for each Java class supported. If
* an unsupported class is found, then the value is just serialized. Conversions
* are done using the {@link DefaultTypeConverter}.
*
* @author Derek Hulley
* @since 3.3
*/
public class DefaultPropertyTypeConverter implements PropertyTypeConverter
{
private static final Log logger = LogFactory.getLog(DefaultPropertyTypeConverter.class);
/**
* Default constructor
*/
public DefaultPropertyTypeConverter()
{
}
/**
* {@inheritDoc}
* <p/>
* This converter looks up a {@link PersistedType} using the <code>class</code> of the
* given value. <tt>null</tt> values are handled specially. If there is no match, then
* the {@link PersistedType#SERIALIZABLE} type is used.
*/
public Pair<Short, Serializable> convertToPersistedType(Serializable value)
{
if (value == null)
{
return PropertyValueEntity.PERSISTED_TYPE_NULL;
}
// Look up the type in the class map
Class<?> clazz = value.getClass();
PersistedType type = PropertyValueEntity.persistedTypesByClass.get(clazz);
if (type == null)
{
return new Pair<Short, Serializable>(PersistedType.SERIALIZABLE.getOrdinalNumber(), value);
}
else
{
// Convert the value
Class<?> toClazz = type.getAssociatedClass();
try
{
Serializable converted = (Serializable) DefaultTypeConverter.INSTANCE.convert(toClazz, value);
return new Pair<Short, Serializable>(type.getOrdinalNumber(), converted);
}
catch (TypeConversionException e)
{
throw new AlfrescoRuntimeException(
"Failed to convert to persistable value: \n" +
" Value: " + value.getClass() + "\n" +
" Target type: " + type + "\n" +
" Target class: " + toClazz,
e);
}
}
}
/**
* {@inheritDoc}
* <p/>
* Looks up the {@link #persistedTypesByOrdinal persisted type} and uses the {@link DefaultTypeConverter} to
* convert back to an external value.
*/
public Serializable convertFromPersistedType(Short persistedType, Class<?> actualType, Serializable persistedValue)
{
if (persistedValue == null)
{
throw new IllegalArgumentException("A persisted value can never be null");
}
PersistedType type = PropertyValueEntity.persistedTypesByOrdinal.get(persistedType);
if (type == null)
{
// Not recognised! This is probably a data issue
logger.warn("Persisted type of '" + persistedType + "' not recognised.");
return persistedValue;
}
else if (type == PersistedType.SERIALIZABLE)
{
// No conversion necessary
return persistedValue;
}
// Convert the value
try
{
return (Serializable) DefaultTypeConverter.INSTANCE.convert(actualType, persistedValue);
}
catch (TypeConversionException e)
{
throw new AlfrescoRuntimeException(
"Failed to convert from persisted value: \n" +
" Value: " + persistedValue.getClass() + "\n" +
" Source type: " + type + "\n" +
" Target class: " + actualType,
e);
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* 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, or (at your option) any later version.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.Pair;
/**
* Entity bean for <b>alf_prop_numeric_value</b> table.
*
* @author Derek Hulley
* @since 3.3
*/
public class PropertyDoubleValueEntity
{
private Long id;
private Double doubleValue;
public PropertyDoubleValueEntity()
{
}
@Override
public int hashCode()
{
return (doubleValue == null ? 0 : doubleValue.hashCode());
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && obj instanceof PropertyDoubleValueEntity)
{
PropertyDoubleValueEntity that = (PropertyDoubleValueEntity) obj;
return EqualsHelper.nullSafeEquals(this.doubleValue, that.doubleValue);
}
else
{
return false;
}
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyNumericValueEntity")
.append("[ ID=").append(id)
.append(", value=").append(doubleValue)
.append("]");
return sb.toString();
}
/**
* @return Returns the ID-value pair
*/
public Pair<Long, Double> getEntityPair()
{
return new Pair<Long, Double>(id, doubleValue);
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public double getDoubleValue()
{
return doubleValue;
}
public void setDoubleValue(Double doubleValue)
{
this.doubleValue = doubleValue;
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* 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, or (at your option) any later version.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import java.io.Serializable;
import org.alfresco.util.Pair;
/**
* Interface for converters that
*
* @author Derek Hulley
* @since 3.3
*/
public interface PropertyTypeConverter
{
/**
* Convert an external value into a persisted type and persistable value.
*
* @param value the value to convert
* @return Returns the persisted type and value to persist
*/
Pair<Short, Serializable> convertToPersistedType(Serializable value);
/**
* Convert a persisted type-value pair into an external value
*
* @param persistedType the type that the value was persisted as
* @param actualType the original Java type to convert to
* @param persistedValue the persisted value, which must be one of the {@link PersistedType} values
*/
Serializable convertFromPersistedType(Short persistedType, Class<?> actualType, Serializable persistedValue);
}

View File

@@ -24,6 +24,8 @@
*/
package org.alfresco.repo.domain.propval;
import java.io.Serializable;
import org.alfresco.util.Pair;
/**
@@ -36,31 +38,77 @@ public interface PropertyValueDAO
{
/**
* <b>alf_prop_class</b> accessor
*
* @param id the ID (may not be <tt>null</tt>)
*/
Pair<Long, Class<?>> getPropertyClass(Long id);
Pair<Long, Class<?>> getPropertyClassById(Long id);
/**
* <b>alf_prop_class</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, Class<?>> getPropertyClass(Class<?> value);
/**
* <b>alf_prop_class</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, Class<?>> getOrCreatePropertyClass(Class<?> value);
/**
* <b>alf_prop_string_value</b> accessor
*
* @param id the ID (may not be <tt>null</tt>)
*/
Pair<Long, String> getPropertyStringValue(Long id);
Pair<Long, String> getPropertyStringValueById(Long id);
/**
* <b>alf_prop_string_value</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, String> getPropertyStringValue(String value);
/**
* <b>alf_prop_string_value</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, String> getOrCreatePropertyStringValue(String value);
/**
* <b>alf_prop_double_value</b> accessor
*
* @param id the ID (may not be <tt>null</tt>)
*/
Pair<Long, Double> getPropertyDoubleValueById(Long id);
/**
* <b>alf_prop_double_value</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, Double> getPropertyDoubleValue(Double value);
/**
* <b>alf_prop_double_value</b> accessor
*
* @param value the value to find the ID for (may not be <tt>null</tt>)
*/
Pair<Long, Double> getOrCreatePropertyDoubleValue(Double value);
/**
* <b>alf_prop_value</b> accessor
*
* @param id the ID (may not be <tt>null</tt>)
*/
Pair<Long, Serializable> getPropertyValueById(Long id);
/**
* <b>alf_prop_value</b> accessor
*
* @param value the value to find the ID for (may be <tt>null</tt>)
*/
Pair<Long, Serializable> getPropertyValue(Serializable value);
/**
* <b>alf_prop_value</b> accessor
*
* @param value the value to find the ID for (may be <tt>null</tt>)
*/
Pair<Long, Serializable> getOrCreatePropertyValue(Serializable value);
}

View File

@@ -78,7 +78,7 @@ public class PropertyValueDAOTest extends TestCase
{
public Void execute() throws Throwable
{
Pair<Long, Class<?>> checkPair1 = propertyValueDAO.getPropertyClass(clazzEntityPair.getFirst());
Pair<Long, Class<?>> checkPair1 = propertyValueDAO.getPropertyClassById(clazzEntityPair.getFirst());
assertEquals(clazzEntityPair, checkPair1);
Pair<Long, Class<?>> checkPair2 = propertyValueDAO.getPropertyClass(clazzEntityPair.getSecond());
assertEquals(clazzEntityPair, checkPair2);
@@ -92,7 +92,7 @@ public class PropertyValueDAOTest extends TestCase
{
public Void execute() throws Throwable
{
propertyValueDAO.getPropertyClass(Long.MIN_VALUE);
propertyValueDAO.getPropertyClassById(Long.MIN_VALUE);
return null;
}
};
@@ -121,7 +121,7 @@ public class PropertyValueDAOTest extends TestCase
public void testPropertyStringValue() throws Exception
{
final String stringValue = "One Two Three";
final String stringValue = "One Two Three - " + System.currentTimeMillis();
final String stringValueUpper = stringValue.toUpperCase();
final String stringValueLower = stringValue.toLowerCase();
RetryingTransactionCallback<Pair<Long, String>> createStringCallback = new RetryingTransactionCallback<Pair<Long, String>>()
@@ -168,4 +168,87 @@ public class PropertyValueDAOTest extends TestCase
assertEquals(stringValueUpper, stringUpperEntityPair.getSecond());
assertNotSame("String IDs were not different", stringEntityPair.getFirst(), stringUpperEntityPair.getFirst());
}
// public void testPropertyNumericValue_Boolean() throws Exception
// {
// RetryingTransactionCallback<Pair<Long, Boolean>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Boolean>>()
// {
// public Pair<Long, Boolean> execute() throws Throwable
// {
// // Get the classes
// return propertyValueDAO.getOrCreatePropertyNumericValue(Boolean.TRUE);
// }
// };
// final Pair<Long, Boolean> entityPair = txnHelper.doInTransaction(createValueCallback, false);
// assertNotNull(entityPair);
// assertEquals(Boolean.TRUE, entityPair.getSecond());
//
// RetryingTransactionCallback<Pair<Long, Boolean>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Boolean>>()
// {
// public Pair<Long, Boolean> execute() throws Throwable
// {
// // Get the classes
// return propertyValueDAO.getPropertyDoubleValue(Boolean.TRUE);
// }
// };
// final Pair<Long, Boolean> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
// assertNotNull(entityPairCheck);
// assertEquals(entityPair, entityPairCheck);
// }
//
// public void testPropertyNumericValue_Long() throws Exception
// {
// final Long longValue = Long.valueOf(Long.MAX_VALUE);
// RetryingTransactionCallback<Pair<Long, Long>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Long>>()
// {
// public Pair<Long, Long> execute() throws Throwable
// {
// // Get the classes
// return propertyValueDAO.getOrCreatePropertyNumericValue(longValue);
// }
// };
// final Pair<Long, Long> entityPair = txnHelper.doInTransaction(createValueCallback, false);
// assertNotNull(entityPair);
// assertEquals(longValue, entityPair.getSecond());
//
// RetryingTransactionCallback<Pair<Long, Long>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Long>>()
// {
// public Pair<Long, Long> execute() throws Throwable
// {
// // Get the classes
// return propertyValueDAO.getPropertyDoubleValue(longValue);
// }
// };
// final Pair<Long, Long> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
// assertNotNull(entityPairCheck);
// assertEquals(entityPair, entityPairCheck);
// }
public void testPropertyDoubleValue() throws Exception
{
final Double doubleValue = Double.valueOf(1.7976931348623E+308);
RetryingTransactionCallback<Pair<Long, Double>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Double>>()
{
public Pair<Long, Double> execute() throws Throwable
{
// Get the classes
return propertyValueDAO.getOrCreatePropertyDoubleValue(doubleValue);
}
};
final Pair<Long, Double> entityPair = txnHelper.doInTransaction(createValueCallback, false);
assertNotNull(entityPair);
assertEquals(doubleValue, entityPair.getSecond());
RetryingTransactionCallback<Pair<Long, Double>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Double>>()
{
public Pair<Long, Double> execute() throws Throwable
{
// Get the classes
return propertyValueDAO.getPropertyDoubleValue(doubleValue);
}
};
final Pair<Long, Double> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
assertNotNull(entityPairCheck);
assertEquals(entityPair, entityPairCheck);
}
}

View File

@@ -0,0 +1,377 @@
/*
* Copyright (C) 2005-2009 Alfresco Software Limited.
*
* 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, or (at your option) any later version.
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.domain.propval;
import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Entity bean for <b>alf_prop_value</b> table.
* <p>
* Values here are either simple values that can be stored in a <code>long</code>
* or will be references to data in other tables.
*
* @author Derek Hulley
* @since 3.3
*/
public class PropertyValueEntity
{
public static final Long LONG_ZERO = new Long(0L);
public static final Long LONG_ONE = new Long(1L);
public static final Short ORDINAL_NULL = new Short((short)0);
public static final Short ORDINAL_BOOLEAN = new Short((short)1);
public static final Short ORDINAL_LONG = new Short((short)2);
public static final Short ORDINAL_DOUBLE = new Short((short)3);
public static final Short ORDINAL_STRING = new Short((short)4);
public static final Short ORDINAL_SERIALIZABLE = new Short((short)5);
/**
* Enumeration of persisted types for <b>alf_prop_value.persisted_type</b>.
* <p/>
* This enumeration is a helper for the default implementation of the {@link PropertyTypeConverter}
* and should not be used in public interfaces.
*
* @author Derek Hulley
* @since 3.3
*/
public static enum PersistedType
{
NULL
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_NULL;
}
@Override
public Class<?> getAssociatedClass()
{
throw new UnsupportedOperationException("NULL is a special case and has no associated class.");
}
},
BOOLEAN
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_BOOLEAN;
}
@Override
public Class<?> getAssociatedClass()
{
return Boolean.class;
}
},
LONG
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_LONG;
}
@Override
public Class<?> getAssociatedClass()
{
return Long.class;
}
},
DOUBLE
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_DOUBLE;
}
@Override
public Class<?> getAssociatedClass()
{
return Double.class;
}
},
STRING
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_STRING;
}
@Override
public Class<?> getAssociatedClass()
{
return String.class;
}
},
SERIALIZABLE
{
@Override
public Short getOrdinalNumber()
{
return ORDINAL_SERIALIZABLE;
}
@Override
public Class<?> getAssociatedClass()
{
return Serializable.class;
}
};
/**
* Fetch the numerical value that will represent the the persisted type. This is done
* explicitly to prevent ordering issues if further types are added.
*
* @return Returns the ordinal number
*/
public abstract Short getOrdinalNumber();
/**
* Get the persisted type's class. This is used for determining the source type when
* converting from persisted values.
*
* @return Returns the class associated with the persisted type
*/
public abstract Class<?> getAssociatedClass();
}
public static final Pair<Short, Serializable> PERSISTED_TYPE_NULL;
/**
* An unmodifiable map of persisted type enums keyed by their ordinal number
*/
public static final Map<Short, PersistedType> persistedTypesByOrdinal;
/**
* An unmodifiable map of persisted type enums keyed by the classes they store
*/
public static final Map<Class<?>, PersistedType> persistedTypesByClass;
static
{
// Create a pair for null values
PERSISTED_TYPE_NULL = new Pair<Short, Serializable>(PersistedType.NULL.getOrdinalNumber(), new Long(0));
// Create the map of ordinal-type
Map<Short, PersistedType> mapOrdinal = new HashMap<Short, PersistedType>(15);
for (PersistedType persistedType : PersistedType.values())
{
mapOrdinal.put(persistedType.getOrdinalNumber(), persistedType);
}
persistedTypesByOrdinal = Collections.unmodifiableMap(mapOrdinal);
// Create the map of class-type
Map<Class<?>, PersistedType> mapClass = new HashMap<Class<?>, PersistedType>(29);
mapClass.put(Boolean.class, PersistedType.BOOLEAN);
mapClass.put(Short.class, PersistedType.LONG);
mapClass.put(Integer.class, PersistedType.LONG);
mapClass.put(Long.class, PersistedType.LONG);
mapClass.put(Float.class, PersistedType.DOUBLE);
mapClass.put(Double.class, PersistedType.DOUBLE);
mapClass.put(String.class, PersistedType.STRING);
mapClass.put(Date.class, PersistedType.LONG);
persistedTypesByClass = Collections.unmodifiableMap(mapClass);
}
private static final Log logger = LogFactory.getLog(PropertyValueEntity.class);
private Long id;
private Short persistedType;
private Long longValue;
private String stringValue;
private Double doubleValue;
private Serializable serializableValue;
public PropertyValueEntity()
{
this.persistedType = PersistedType.NULL.getOrdinalNumber();
this.longValue = LONG_ZERO;
}
@Override
public int hashCode()
{
return (persistedType == null ? 0 : persistedType.intValue()) + (longValue == null ? 0 : longValue.intValue());
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && obj instanceof PropertyValueEntity)
{
PropertyValueEntity that = (PropertyValueEntity) obj;
return EqualsHelper.nullSafeEquals(this.persistedType, that.persistedType) &&
EqualsHelper.nullSafeEquals(this.longValue, that.longValue);
}
else
{
return false;
}
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("PropertyValueEntity")
.append("[ ID=").append(id)
.append(", type=").append(persistedType)
.append(", value=").append(longValue)
.append("]");
return sb.toString();
}
/**
* @return Returns the ID-value pair
*/
public Pair<Long, Serializable> getEntityPair()
{
Serializable value = getValue();
return new Pair<Long, Serializable>(id, value);
}
/**
* Gets the value based on the persisted type.
* Note that this is the value <b>as persisted</b> and not the original, client-required
* value.
* @return Returns the persisted value
*/
public Serializable getValue()
{
if (persistedType.equals(PersistedType.NULL.getOrdinalNumber()))
{
return null;
}
else if (persistedType.equals(PersistedType.BOOLEAN.getOrdinalNumber()))
{
return (longValue.longValue() > 0 ? Boolean.TRUE : Boolean.FALSE);
}
else if (persistedType.equals(PersistedType.LONG.getOrdinalNumber()))
{
return longValue;
}
else if (persistedType.equals(PersistedType.DOUBLE.getOrdinalNumber()))
{
return doubleValue;
}
else if (persistedType.equals(PersistedType.STRING.getOrdinalNumber()))
{
return stringValue;
}
else if (persistedType.equals(PersistedType.SERIALIZABLE.getOrdinalNumber()))
{
return serializableValue;
}
else
{
logger.warn("Persisted type code not recognised: " + this.persistedType);
// Return any non-null value and hope it works
if (serializableValue != null)
{
return serializableValue;
}
else if (doubleValue != null)
{
return doubleValue;
}
else if (stringValue != null)
{
return stringValue;
}
else
{
return longValue;
}
}
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public Short getPersistedType()
{
return persistedType;
}
public void setPersistedType(Short persistedType)
{
this.persistedType = persistedType;
}
public Long getLongValue()
{
return longValue;
}
public void setLongValue(Long longValue)
{
this.longValue = longValue;
}
public String getStringValue()
{
return stringValue;
}
public void setStringValue(String stringValue)
{
this.stringValue = stringValue;
}
public Double getDoubleValue()
{
return doubleValue;
}
public void setDoubleValue(Double doubleValue)
{
this.doubleValue = doubleValue;
}
public Serializable getSerializableValue()
{
return serializableValue;
}
public void setSerializableValue(Serializable serializableValue)
{
this.serializableValue = serializableValue;
}
}

View File

@@ -24,11 +24,16 @@
*/
package org.alfresco.repo.domain.propval.ibatis;
import java.io.Serializable;
import java.util.List;
import org.alfresco.repo.domain.propval.AbstractPropertyValueDAOImpl;
import org.alfresco.repo.domain.propval.PropertyClassEntity;
import org.alfresco.repo.domain.propval.PropertyDoubleValueEntity;
import org.alfresco.repo.domain.propval.PropertyStringValueEntity;
import org.alfresco.repo.domain.propval.PropertyValueEntity;
import org.alfresco.repo.domain.propval.PropertyValueEntity.PersistedType;
import org.alfresco.util.Pair;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
/**
@@ -39,13 +44,16 @@ import org.springframework.orm.ibatis.SqlMapClientTemplate;
*/
public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
{
private static final Long VERSION_ONE = new Long(1L);
private static final String SELECT_PROPERTY_CLASS_BY_ID = "select.PropertyClassByID";
private static final String SELECT_PROPERTY_CLASS_BY_NAME = "select.PropertyClassByName";
private static final String INSERT_PROPERTY_CLASS = "insert.PropertyClass";
private static final String SELECT_PROPERTY_STRING_VALUE_BY_ID = "select.PropertyStringValueByID";
private static final String SELECT_PROPERTY_STRING_VALUE_BY_STRING = "select.PropertyStringValueByString";
private static final String INSERT_PROPERTY_STRING_VALUE = "insert.PropertyStringValue";
private static final String SELECT_PROPERTY_DOUBLE_VALUE_BY_ID = "select.PropertyDoubleValueByID";
private static final String SELECT_PROPERTY_DOUBLE_VALUE_BY_VALUE = "select.PropertyDoubleValueByValue";
private static final String INSERT_PROPERTY_DOUBLE_VALUE = "insert.PropertyDoubleValue";
private static final String INSERT_PROPERTY_VALUE = "insert.PropertyValue";
private SqlMapClientTemplate template;
@@ -54,12 +62,18 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
this.template = sqlMapClientTemplate;
}
//================================
// 'alf_prop_class' accessors
//================================
@Override
protected PropertyClassEntity findClassById(Long id)
{
PropertyClassEntity entity = new PropertyClassEntity();
entity.setId(id);
entity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_ID, entity);
entity = (PropertyClassEntity) template.queryForObject(
SELECT_PROPERTY_CLASS_BY_ID,
entity);
// Done
return entity;
}
@@ -69,7 +83,9 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
{
PropertyClassEntity entity = new PropertyClassEntity();
entity.setJavaClass(value);
entity = (PropertyClassEntity) template.queryForObject(SELECT_PROPERTY_CLASS_BY_NAME, entity);
entity = (PropertyClassEntity) template.queryForObject(
SELECT_PROPERTY_CLASS_BY_NAME,
entity);
// Done
return entity;
}
@@ -85,12 +101,18 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
return entity;
}
//================================
// 'alf_prop_string_value' accessors
//================================
@Override
protected PropertyStringValueEntity findStringValueById(Long id)
{
PropertyStringValueEntity entity = new PropertyStringValueEntity();
entity.setId(id);
entity = (PropertyStringValueEntity) template.queryForObject(SELECT_PROPERTY_STRING_VALUE_BY_ID, entity);
entity = (PropertyStringValueEntity) template.queryForObject(
SELECT_PROPERTY_STRING_VALUE_BY_ID,
entity);
// Done
return entity;
}
@@ -101,8 +123,10 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
{
PropertyStringValueEntity entity = new PropertyStringValueEntity();
entity.setStringValue(value);
List<PropertyStringValueEntity> results = (List<PropertyStringValueEntity>) template.queryForList(SELECT_PROPERTY_STRING_VALUE_BY_STRING, entity);
// There are several matches, so find the first one that matches exactly
List<PropertyStringValueEntity> results = (List<PropertyStringValueEntity>) template.queryForList(
SELECT_PROPERTY_STRING_VALUE_BY_STRING,
entity);
// There double be several matches, so find the first one that matches exactly
for (PropertyStringValueEntity resultEntity : results)
{
if (value.equals(resultEntity.getStringValue()))
@@ -125,4 +149,134 @@ public class PropertyValueDAOImpl extends AbstractPropertyValueDAOImpl
// Done
return entity;
}
//================================
// 'alf_prop_double_value' accessors
//================================
@Override
protected PropertyDoubleValueEntity findDoubleValueById(Long id)
{
PropertyDoubleValueEntity entity = new PropertyDoubleValueEntity();
entity.setId(id);
entity = (PropertyDoubleValueEntity) template.queryForObject(
SELECT_PROPERTY_DOUBLE_VALUE_BY_ID,
entity);
// Done
return entity;
}
@SuppressWarnings("unchecked")
@Override
protected PropertyDoubleValueEntity findDoubleValueByValue(Double value)
{
PropertyDoubleValueEntity entity = new PropertyDoubleValueEntity();
entity.setDoubleValue(value);
List<PropertyDoubleValueEntity> results = (List<PropertyDoubleValueEntity>) template.queryForList(
SELECT_PROPERTY_DOUBLE_VALUE_BY_VALUE,
entity);
// There coult be several matches, so find the first one that matches exactly
for (PropertyDoubleValueEntity resultEntity : results)
{
if (value.equals(resultEntity.getDoubleValue()))
{
// Found a match
return resultEntity;
}
}
// No real match
return null;
}
@Override
protected PropertyDoubleValueEntity createDoubleValue(Double value)
{
PropertyDoubleValueEntity entity = new PropertyDoubleValueEntity();
entity.setDoubleValue(value);
Long id = (Long) template.insert(INSERT_PROPERTY_DOUBLE_VALUE, entity);
entity.setId(id);
// Done
return entity;
}
//================================
// 'alf_prop_value' accessors
//================================
@Override
protected PropertyValueEntity findPropertyValueById(Long id)
{
// TODO: Full query pulling back all related values
return null;
}
@Override
protected PropertyValueEntity findPropertyValueByValue(Serializable value)
{
// TODO: Find out persisted type and perform relevant query
return null;
}
@Override
protected PropertyValueEntity createPropertyValue(Serializable value)
{
// Find out how it would be persisted
Pair<Short, Serializable> persistedValuePair = converter.convertToPersistedType(value);
Serializable persistedValue = persistedValuePair.getSecond();
PropertyValueEntity entity = new PropertyValueEntity();
PersistedType persistedType = PropertyValueEntity.persistedTypesByOrdinal.get(persistedValuePair.getFirst());
entity.setPersistedType(persistedType.getOrdinalNumber());
// Handle each persisted type individually
if (persistedType.equals(PersistedType.NULL.getOrdinalNumber()))
{
entity.setLongValue(PropertyValueEntity.LONG_ZERO);
}
else if (persistedType.equals(PersistedType.BOOLEAN.getOrdinalNumber()))
{
Boolean booleanValue = (Boolean) persistedValue;
entity.setLongValue(
booleanValue.booleanValue() ? PropertyValueEntity.LONG_ONE : PropertyValueEntity.LONG_ZERO);
}
else if (persistedType.equals(PersistedType.LONG.getOrdinalNumber()))
{
Long longValue = (Long) persistedValue;
entity.setLongValue(longValue);
}
else if (persistedType.equals(PersistedType.DOUBLE.getOrdinalNumber()))
{
Double doubleValue = (Double) persistedValue;
// Look it up
Pair<Long, Double> entityPair = getOrCreatePropertyDoubleValue(doubleValue);
entity.setLongValue(entityPair.getFirst());
entity.setDoubleValue(doubleValue);
}
else if (persistedType.equals(PersistedType.STRING.getOrdinalNumber()))
{
String stringValue = (String) persistedValue;
// Look it up
Pair<Long, String> entityPair = getOrCreatePropertyStringValue(stringValue);
entity.setLongValue(entityPair.getFirst());
entity.setStringValue(stringValue);
}
else if (persistedType.equals(PersistedType.SERIALIZABLE.getOrdinalNumber()))
{
throw new UnsupportedOperationException("Serializable not done, yet.");
}
else
{
throw new IllegalStateException(
"The persisted property is not valid: \n" +
" Raw Value: " + value + "\n" +
" Persisted Value: " + persistedValuePair + "\n" +
" Converter:" + converter.getClass());
}
// Persist the entity
Long id = (Long) template.insert(INSERT_PROPERTY_VALUE, entity);
entity.setId(id);
// Done
return entity;
}
}