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);
}
diff --git a/source/java/org/alfresco/repo/domain/propval/DefaultPropertyTypeConverter.java b/source/java/org/alfresco/repo/domain/propval/DefaultPropertyTypeConverter.java
new file mode 100644
index 0000000000..4674ee1d31
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/propval/DefaultPropertyTypeConverter.java
@@ -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.
+ *
+ * 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}
+ *
+ * This converter looks up a {@link PersistedType} using the class
of the
+ * given value. null values are handled specially. If there is no match, then
+ * the {@link PersistedType#SERIALIZABLE} type is used.
+ */
+ public Pair 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(PersistedType.SERIALIZABLE.getOrdinalNumber(), value);
+ }
+ else
+ {
+ // Convert the value
+ Class> toClazz = type.getAssociatedClass();
+ try
+ {
+ Serializable converted = (Serializable) DefaultTypeConverter.INSTANCE.convert(toClazz, value);
+ return new Pair(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}
+ *
+ * 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);
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyDoubleValueEntity.java b/source/java/org/alfresco/repo/domain/propval/PropertyDoubleValueEntity.java
new file mode 100644
index 0000000000..0f70fdb4f6
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyDoubleValueEntity.java
@@ -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 alf_prop_numeric_value 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 getEntityPair()
+ {
+ return new Pair(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;
+ }
+}
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyTypeConverter.java b/source/java/org/alfresco/repo/domain/propval/PropertyTypeConverter.java
new file mode 100644
index 0000000000..293ff4ea1c
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyTypeConverter.java
@@ -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 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);
+}
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
index afb0f3c913..7a0320c619 100644
--- a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAO.java
@@ -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
{
/**
* alf_prop_class accessor
+ *
+ * @param id the ID (may not be null)
*/
- Pair> getPropertyClass(Long id);
-
+ Pair> getPropertyClassById(Long id);
/**
* alf_prop_class accessor
+ *
+ * @param value the value to find the ID for (may not be null)
*/
Pair> getPropertyClass(Class> value);
-
/**
* alf_prop_class accessor
+ *
+ * @param value the value to find the ID for (may not be null)
*/
Pair> getOrCreatePropertyClass(Class> value);
/**
* alf_prop_string_value accessor
+ *
+ * @param id the ID (may not be null)
*/
- Pair getPropertyStringValue(Long id);
-
+ Pair getPropertyStringValueById(Long id);
/**
* alf_prop_string_value accessor
+ *
+ * @param value the value to find the ID for (may not be null)
*/
Pair getPropertyStringValue(String value);
-
/**
* alf_prop_string_value accessor
+ *
+ * @param value the value to find the ID for (may not be null)
*/
Pair getOrCreatePropertyStringValue(String value);
+
+ /**
+ * alf_prop_double_value accessor
+ *
+ * @param id the ID (may not be null)
+ */
+ Pair getPropertyDoubleValueById(Long id);
+ /**
+ * alf_prop_double_value accessor
+ *
+ * @param value the value to find the ID for (may not be null)
+ */
+ Pair getPropertyDoubleValue(Double value);
+ /**
+ * alf_prop_double_value accessor
+ *
+ * @param value the value to find the ID for (may not be null)
+ */
+ Pair getOrCreatePropertyDoubleValue(Double value);
+
+ /**
+ * alf_prop_value accessor
+ *
+ * @param id the ID (may not be null)
+ */
+ Pair getPropertyValueById(Long id);
+ /**
+ * alf_prop_value accessor
+ *
+ * @param value the value to find the ID for (may be null)
+ */
+ Pair getPropertyValue(Serializable value);
+ /**
+ * alf_prop_value accessor
+ *
+ * @param value the value to find the ID for (may be null)
+ */
+ Pair getOrCreatePropertyValue(Serializable value);
}
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java
index af955df2c5..e4b8bde6d5 100644
--- a/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueDAOTest.java
@@ -78,7 +78,7 @@ public class PropertyValueDAOTest extends TestCase
{
public Void execute() throws Throwable
{
- Pair> checkPair1 = propertyValueDAO.getPropertyClass(clazzEntityPair.getFirst());
+ Pair> checkPair1 = propertyValueDAO.getPropertyClassById(clazzEntityPair.getFirst());
assertEquals(clazzEntityPair, checkPair1);
Pair> 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> createStringCallback = new RetryingTransactionCallback>()
@@ -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> createValueCallback = new RetryingTransactionCallback>()
+// {
+// public Pair execute() throws Throwable
+// {
+// // Get the classes
+// return propertyValueDAO.getOrCreatePropertyNumericValue(Boolean.TRUE);
+// }
+// };
+// final Pair entityPair = txnHelper.doInTransaction(createValueCallback, false);
+// assertNotNull(entityPair);
+// assertEquals(Boolean.TRUE, entityPair.getSecond());
+//
+// RetryingTransactionCallback> getValueCallback = new RetryingTransactionCallback>()
+// {
+// public Pair execute() throws Throwable
+// {
+// // Get the classes
+// return propertyValueDAO.getPropertyDoubleValue(Boolean.TRUE);
+// }
+// };
+// final Pair 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> createValueCallback = new RetryingTransactionCallback>()
+// {
+// public Pair execute() throws Throwable
+// {
+// // Get the classes
+// return propertyValueDAO.getOrCreatePropertyNumericValue(longValue);
+// }
+// };
+// final Pair entityPair = txnHelper.doInTransaction(createValueCallback, false);
+// assertNotNull(entityPair);
+// assertEquals(longValue, entityPair.getSecond());
+//
+// RetryingTransactionCallback> getValueCallback = new RetryingTransactionCallback>()
+// {
+// public Pair execute() throws Throwable
+// {
+// // Get the classes
+// return propertyValueDAO.getPropertyDoubleValue(longValue);
+// }
+// };
+// final Pair entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
+// assertNotNull(entityPairCheck);
+// assertEquals(entityPair, entityPairCheck);
+// }
+
+ public void testPropertyDoubleValue() throws Exception
+ {
+ final Double doubleValue = Double.valueOf(1.7976931348623E+308);
+ RetryingTransactionCallback> createValueCallback = new RetryingTransactionCallback>()
+ {
+ public Pair execute() throws Throwable
+ {
+ // Get the classes
+ return propertyValueDAO.getOrCreatePropertyDoubleValue(doubleValue);
+ }
+ };
+ final Pair entityPair = txnHelper.doInTransaction(createValueCallback, false);
+ assertNotNull(entityPair);
+ assertEquals(doubleValue, entityPair.getSecond());
+
+ RetryingTransactionCallback> getValueCallback = new RetryingTransactionCallback>()
+ {
+ public Pair execute() throws Throwable
+ {
+ // Get the classes
+ return propertyValueDAO.getPropertyDoubleValue(doubleValue);
+ }
+ };
+ final Pair entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
+ assertNotNull(entityPairCheck);
+ assertEquals(entityPair, entityPairCheck);
+ }
}
diff --git a/source/java/org/alfresco/repo/domain/propval/PropertyValueEntity.java b/source/java/org/alfresco/repo/domain/propval/PropertyValueEntity.java
new file mode 100644
index 0000000000..e2168c12f7
--- /dev/null
+++ b/source/java/org/alfresco/repo/domain/propval/PropertyValueEntity.java
@@ -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 alf_prop_value table.
+ *
+ * Values here are either simple values that can be stored in a long
+ * 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 alf_prop_value.persisted_type.
+ *
+ * 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 PERSISTED_TYPE_NULL;
+ /**
+ * An unmodifiable map of persisted type enums keyed by their ordinal number
+ */
+ public static final Map persistedTypesByOrdinal;
+
+ /**
+ * An unmodifiable map of persisted type enums keyed by the classes they store
+ */
+ public static final Map, PersistedType> persistedTypesByClass;
+
+ static
+ {
+ // Create a pair for null values
+ PERSISTED_TYPE_NULL = new Pair(PersistedType.NULL.getOrdinalNumber(), new Long(0));
+ // Create the map of ordinal-type
+ Map mapOrdinal = new HashMap(15);
+ for (PersistedType persistedType : PersistedType.values())
+ {
+ mapOrdinal.put(persistedType.getOrdinalNumber(), persistedType);
+ }
+ persistedTypesByOrdinal = Collections.unmodifiableMap(mapOrdinal);
+ // Create the map of class-type
+ Map, PersistedType> mapClass = new HashMap, 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 getEntityPair()
+ {
+ Serializable value = getValue();
+ return new Pair(id, value);
+ }
+
+ /**
+ * Gets the value based on the persisted type.
+ * Note that this is the value as persisted 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;
+ }
+}
diff --git a/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java b/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java
index 5290efddad..56eb2860a6 100644
--- a/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java
+++ b/source/java/org/alfresco/repo/domain/propval/ibatis/PropertyValueDAOImpl.java
@@ -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 results = (List) template.queryForList(SELECT_PROPERTY_STRING_VALUE_BY_STRING, entity);
- // There are several matches, so find the first one that matches exactly
+ List results = (List) 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 results = (List) 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 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 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 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;
+ }
}