mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	71610: Merged V4.2-BUG-FIX (4.2.3) to HEAD-BUG-FIX (4.3/Cloud)
      70771: Merged V4.1-BUG-FIX (4.1.9) to V4.2-BUG-FIX (4.2.3)
         70770: MNT-10067 : Cleanup alf_prop_XXX data
         Disabled a test, as the functionality is not ready, yet.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@74699 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			997 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			997 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2014 Alfresco Software Limited.
 | |
|  *
 | |
|  * This file is part of Alfresco
 | |
|  *
 | |
|  * Alfresco 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 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| package org.alfresco.repo.domain.propval;
 | |
| 
 | |
| import static org.junit.Assert.*;
 | |
| 
 | |
| import java.io.Serializable;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Arrays;
 | |
| import java.util.Collections;
 | |
| import java.util.Date;
 | |
| import java.util.HashMap;
 | |
| import java.util.HashSet;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.Random;
 | |
| 
 | |
| import javax.naming.CompositeName;
 | |
| 
 | |
| import org.alfresco.repo.domain.propval.PropertyValueDAO.PropertyFinderCallback;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper;
 | |
| import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
 | |
| import org.alfresco.service.ServiceRegistry;
 | |
| import org.alfresco.service.transaction.TransactionService;
 | |
| import org.alfresco.test_category.OwnJVMTestsCategory;
 | |
| import org.alfresco.util.ApplicationContextHelper;
 | |
| import org.alfresco.util.GUID;
 | |
| import org.alfresco.util.Pair;
 | |
| import org.junit.experimental.categories.Category;
 | |
| import org.junit.Before;
 | |
| import org.junit.Ignore;
 | |
| import org.junit.Test;
 | |
| import org.springframework.context.ApplicationContext;
 | |
| import org.springframework.dao.DataIntegrityViolationException;
 | |
| import org.springframework.extensions.surf.util.ISO8601DateFormat;
 | |
| 
 | |
| /**
 | |
|  * @see PropertyValueDAO
 | |
|  * 
 | |
|  * @author Derek Hulley
 | |
|  * @since 3.2
 | |
|  */
 | |
| @Category(OwnJVMTestsCategory.class)
 | |
| public class PropertyValueDAOTest
 | |
| {
 | |
|     private ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
 | |
| 
 | |
|     private TransactionService transactionService;
 | |
|     private RetryingTransactionHelper txnHelper;
 | |
|     private PropertyValueDAO propertyValueDAO;
 | |
|     
 | |
|     @Before
 | |
|     public void setUp() throws Exception
 | |
|     {
 | |
|         ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
 | |
|         transactionService = serviceRegistry.getTransactionService();
 | |
|         txnHelper = transactionService.getRetryingTransactionHelper();
 | |
|         txnHelper.setMaxRetries(0);
 | |
|         
 | |
|         propertyValueDAO = (PropertyValueDAO) ctx.getBean("propertyValueDAO");
 | |
|         
 | |
|         // Remove the caches to test all functionality
 | |
|         removeCaches();
 | |
|     }
 | |
|     
 | |
|     private void removeCaches()
 | |
|     {
 | |
|         ((AbstractPropertyValueDAOImpl)propertyValueDAO).setPropertyClassCache(null);
 | |
|         ((AbstractPropertyValueDAOImpl)propertyValueDAO).setPropertyDateValueCache(null);
 | |
|         ((AbstractPropertyValueDAOImpl)propertyValueDAO).setPropertyDoubleValueCache(null);
 | |
|         ((AbstractPropertyValueDAOImpl)propertyValueDAO).setPropertyStringValueCache(null);
 | |
|         ((AbstractPropertyValueDAOImpl)propertyValueDAO).setPropertyValueCache(null);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyClass() throws Exception
 | |
|     {
 | |
|         final Class<?> clazz = this.getClass();
 | |
|         RetryingTransactionCallback<Pair<Long, Class<?>>> createClassCallback = new RetryingTransactionCallback<Pair<Long, Class<?>>>()
 | |
|         {
 | |
|             public Pair<Long, Class<?>> execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 return propertyValueDAO.getOrCreatePropertyClass(clazz);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Class<?>> clazzEntityPair = txnHelper.doInTransaction(createClassCallback, false);
 | |
|         assertNotNull(clazzEntityPair);
 | |
|         assertNotNull(clazzEntityPair.getFirst());
 | |
|         assertEquals(clazz, clazzEntityPair.getSecond());
 | |
|         // Now retrieve it
 | |
|         RetryingTransactionCallback<Void> getClassCallback = new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 Pair<Long, Class<?>> checkPair1 = propertyValueDAO.getPropertyClassById(clazzEntityPair.getFirst());
 | |
|                 assertEquals(clazzEntityPair, checkPair1);
 | |
|                 Pair<Long, Class<?>> checkPair2 = propertyValueDAO.getPropertyClass(clazzEntityPair.getSecond());
 | |
|                 assertEquals(clazzEntityPair, checkPair2);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(getClassCallback, true);
 | |
|         
 | |
|         // Test failure when requesting invalid ID
 | |
|         RetryingTransactionCallback<Void> badGetCallback = new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 propertyValueDAO.getPropertyClassById(Long.MIN_VALUE);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         try
 | |
|         {
 | |
|             txnHelper.doInTransaction(badGetCallback, false);
 | |
|             fail("Expected exception when using invalid ID.");
 | |
|         }
 | |
|         catch (RuntimeException e)
 | |
|         {
 | |
|             // Expected
 | |
|         }
 | |
|         
 | |
|         // Test null caching
 | |
|         RetryingTransactionCallback<Void> noHitCallback = new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 propertyValueDAO.getPropertyClass(this.getClass());
 | |
|                 propertyValueDAO.getPropertyClass(this.getClass());
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(noHitCallback, false);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyDateValue() throws Exception
 | |
|     {
 | |
|         final Date dateValue = ISO8601DateFormat.parse("1936-08-04T23:37:25.793Z");
 | |
|         final Date dateValueBack = ISO8601DateFormat.parse("1936-08-04T00:00:00.000Z");
 | |
|         RetryingTransactionCallback<Pair<Long, Date>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Date>>()
 | |
|         {
 | |
|             public Pair<Long, Date> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.getOrCreatePropertyDateValue(dateValue);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Date> entityPair = txnHelper.doInTransaction(createValueCallback, false);
 | |
|         assertNotNull(entityPair);
 | |
|         assertEquals(dateValueBack, entityPair.getSecond());
 | |
|         
 | |
|         RetryingTransactionCallback<Pair<Long, Date>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Date>>()
 | |
|         {
 | |
|             public Pair<Long, Date> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.getPropertyDateValue(dateValue);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Date> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
 | |
|         assertNotNull(entityPairCheck);
 | |
|         assertEquals(entityPair, entityPairCheck);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyStringValue() throws Exception
 | |
|     {
 | |
|         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>>()
 | |
|         {
 | |
|             public Pair<Long, String> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.getOrCreatePropertyStringValue(stringValue);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, String> stringEntityPair = txnHelper.doInTransaction(createStringCallback, false);
 | |
|         assertNotNull(stringEntityPair);
 | |
|         assertNotNull(stringEntityPair.getFirst());
 | |
|         assertEquals(stringValue, stringEntityPair.getSecond());
 | |
|         
 | |
|         // Check that the uppercase and lowercase strings don't have entries
 | |
|         RetryingTransactionCallback<Void> getStringCallback = new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 Pair<Long, String> checkPair1 = propertyValueDAO.getPropertyStringValue(stringValue);
 | |
|                 assertNotNull(checkPair1);
 | |
|                 assertEquals(stringValue, checkPair1.getSecond());
 | |
|                 Pair<Long, String> checkPair2 = propertyValueDAO.getPropertyStringValue(stringValueUpper);
 | |
|                 assertNull(checkPair2);
 | |
|                 Pair<Long, String> checkPair3 = propertyValueDAO.getPropertyStringValue(stringValueLower);
 | |
|                 assertNull(checkPair3);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(getStringCallback, true);
 | |
| 
 | |
|         RetryingTransactionCallback<Pair<Long, String>> createStringUpperCallback = new RetryingTransactionCallback<Pair<Long, String>>()
 | |
|         {
 | |
|             public Pair<Long, String> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.getOrCreatePropertyStringValue(stringValueUpper);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, String> stringUpperEntityPair = txnHelper.doInTransaction(createStringUpperCallback, false);
 | |
|         assertNotNull(stringUpperEntityPair);
 | |
|         assertNotNull(stringUpperEntityPair.getFirst());
 | |
|         assertEquals(stringValueUpper, stringUpperEntityPair.getSecond());
 | |
|         assertNotSame("String IDs were not different", stringEntityPair.getFirst(), stringUpperEntityPair.getFirst());
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Try to catch Oracle out
 | |
|      */
 | |
|     @Test
 | |
|     public void testPropertyStringValue_EmptyAndNull() throws Exception
 | |
|     {
 | |
|         // Check empty string
 | |
|         RetryingTransactionCallback<Void> emptyStringCallback = new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 Pair<Long, String> emptyStringPair1 = propertyValueDAO.getOrCreatePropertyStringValue("");
 | |
|                 assertNotNull(emptyStringPair1);
 | |
|                 assertEquals("", emptyStringPair1.getSecond());
 | |
|                 Pair<Long, String> emptyStringPair2 = propertyValueDAO.getOrCreatePropertyStringValue("");
 | |
|                 assertNotNull(emptyStringPair2);
 | |
|                 assertEquals(emptyStringPair1, emptyStringPair2);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(emptyStringCallback, false);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyDoubleValue() throws Exception
 | |
|     {
 | |
|         final Double doubleValue = Double.valueOf(1.7976931348623E+125);
 | |
|         RetryingTransactionCallback<Pair<Long, Double>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Double>>()
 | |
|         {
 | |
|             public Pair<Long, Double> execute() throws Throwable
 | |
|             {
 | |
|                 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
 | |
|             {
 | |
|                 return propertyValueDAO.getPropertyDoubleValue(doubleValue);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Double> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
 | |
|         assertNotNull(entityPairCheck);
 | |
|         assertEquals(entityPair, entityPairCheck);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertySerializableValue() throws Exception
 | |
|     {
 | |
|         final Serializable serializableValue = new CompositeName("123");
 | |
|         RetryingTransactionCallback<Pair<Long, Serializable>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.createPropertySerializableValue(serializableValue);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Serializable> entityPair = txnHelper.doInTransaction(createValueCallback, false);
 | |
|         assertNotNull(entityPair);
 | |
|         assertEquals(serializableValue, entityPair.getSecond());
 | |
|         
 | |
|         RetryingTransactionCallback<Pair<Long, Serializable>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.getPropertySerializableValueById(entityPair.getFirst());
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Serializable> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
 | |
|         assertNotNull(entityPairCheck);
 | |
|         assertEquals(entityPair.getFirst(), entityPairCheck.getFirst());
 | |
|         assertEquals(entityPair, entityPairCheck);
 | |
|         
 | |
|         // Check that we can persist and retrieve byte[] as a Serializable
 | |
|         final Serializable bytes = (Serializable) new byte[] {1, 2, 3};
 | |
|         RetryingTransactionCallback<Pair<Long, Void>> testBytesCallback = new RetryingTransactionCallback<Pair<Long, Void>>()
 | |
|         {
 | |
|             public Pair<Long, Void> execute() throws Throwable
 | |
|             {
 | |
|                 Long id = propertyValueDAO.createPropertySerializableValue(bytes).getFirst();
 | |
|                 Serializable check = propertyValueDAO.getPropertySerializableValueById(id).getSecond();
 | |
|                 assertNotNull(check);
 | |
|                 assertTrue(check instanceof byte[]);
 | |
|                 Arrays.equals((byte[])bytes, (byte[])check);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(testBytesCallback, false);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Tests that the given value can be persisted and retrieved with the same resulting ID
 | |
|      */
 | |
|     private void runPropertyValueTest(final Serializable value) throws Exception
 | |
|     {
 | |
|         runPropertyValueTest(value, true);
 | |
|     }
 | |
|     /**
 | |
|      * Tests that the given value can be persisted and retrieved with the same resulting ID
 | |
|      */
 | |
|     private void runPropertyValueTest(final Serializable value, final boolean runValueRetrieval) throws Exception
 | |
|     {
 | |
|         // Create it (if it doesn't exist)
 | |
|         RetryingTransactionCallback<Pair<Long, Serializable>> createValueCallback = new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 return propertyValueDAO.getOrCreatePropertyValue(value);
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Serializable> entityPair = txnHelper.doInTransaction(createValueCallback, false);
 | |
|         assertNotNull(entityPair);
 | |
|         assertEquals(value, entityPair.getSecond());
 | |
|         
 | |
|         if (runValueRetrieval)
 | |
|         {
 | |
|             // Retrieve it by value
 | |
|             RetryingTransactionCallback<Pair<Long, Serializable>> getValueCallback = new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|             {
 | |
|                 public Pair<Long, Serializable> execute() throws Throwable
 | |
|                 {
 | |
|                     // Get the classes
 | |
|                     return propertyValueDAO.getPropertyValue(value);
 | |
|                 }
 | |
|             };
 | |
|             final Pair<Long, Serializable> entityPairCheck = txnHelper.doInTransaction(getValueCallback, false);
 | |
|             assertNotNull(entityPairCheck);
 | |
|             assertEquals(entityPair, entityPairCheck);
 | |
|         }
 | |
|         
 | |
|         // Retrieve it by ID
 | |
|         RetryingTransactionCallback<Pair<Long, Serializable>> getByIdCallback = new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 return propertyValueDAO.getPropertyValueById(entityPair.getFirst());
 | |
|             }
 | |
|         };
 | |
|         final Pair<Long, Serializable> entityPairCheck2 = txnHelper.doInTransaction(getByIdCallback, false);
 | |
|         assertNotNull(entityPairCheck2);
 | |
|         assertEquals(entityPair, entityPairCheck2);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Null() throws Exception
 | |
|     {
 | |
|         runPropertyValueTest(null);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Boolean() throws Exception
 | |
|     {
 | |
|         runPropertyValueTest(Boolean.TRUE);
 | |
|         runPropertyValueTest(Boolean.FALSE);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Short() throws Exception
 | |
|     {
 | |
|         for (short i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Short(i));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Integer() throws Exception
 | |
|     {
 | |
|         for (int i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Integer(i));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Long() throws Exception
 | |
|     {
 | |
|         for (long i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Long(i));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Float() throws Exception
 | |
|     {
 | |
|         for (long i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Float((float)i + 0.01F));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Double() throws Exception
 | |
|     {
 | |
|         for (long i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Double((double)i + 0.01D));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Date() throws Exception
 | |
|     {
 | |
|         Random rand = new Random();
 | |
|         for (long i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new Date(rand.nextLong()));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_String() throws Exception
 | |
|     {
 | |
|         for (long i = 0; i < 100; i++)
 | |
|         {
 | |
|             runPropertyValueTest(new String("Value-" + i + ".xyz"));
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Serializable() throws Exception
 | |
|     {
 | |
|         for (int i = 0; i < 100; i++)
 | |
|         {
 | |
|             // Choose a type that implements equals and hashCode but will not be recognised
 | |
|             runPropertyValueTest(new CompositeName("Name-"+i), false);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private static enum TEST_NUMBERS
 | |
|     {
 | |
|         ONE, TWO, THREE;
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_Enum() throws Exception
 | |
|     {
 | |
|         for (int i = 0; i < 3; i++)
 | |
|         {
 | |
|             TEST_NUMBERS n = TEST_NUMBERS.values()[i];
 | |
|             runPropertyValueTest(n);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_EmptyHashMap() throws Exception
 | |
|     {
 | |
|         final HashMap<String, String> map = new HashMap<String, String>(15);
 | |
|         runPropertyValueTest(map, true);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_EmptyArrayList() throws Exception
 | |
|     {
 | |
|         final ArrayList<String> list = new ArrayList<String>(20);
 | |
|         runPropertyValueTest(list, true);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_EmptyHashSet() throws Exception
 | |
|     {
 | |
|         final HashSet<String> set = new HashSet<String>(20);
 | |
|         runPropertyValueTest(set, true);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyValue_MapOfStrings() throws Exception
 | |
|     {
 | |
|         final HashMap<String, String> map = new HashMap<String, String>(15);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String key = "MAP-KEY-" + i;
 | |
|             String value = "MAP-VALUE-" + i;
 | |
|             map.put(key, value);
 | |
|         }
 | |
|         runPropertyValueTest(map, false);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Tests that the given value can be persisted and retrieved with the same resulting ID
 | |
|      */
 | |
|     private Long runPropertyTest(final Serializable value) throws Exception
 | |
|     {
 | |
|         // Create it
 | |
|         RetryingTransactionCallback<Long> createValueCallback = new RetryingTransactionCallback<Long>()
 | |
|         {
 | |
|             public Long execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 return propertyValueDAO.createProperty(value);
 | |
|             }
 | |
|         };
 | |
|         final Long entityId = txnHelper.doInTransaction(createValueCallback, false);
 | |
|         assertNotNull(entityId);
 | |
|         
 | |
|         // Retrieve it by ID
 | |
|         RetryingTransactionCallback<Serializable> getByIdCallback = new RetryingTransactionCallback<Serializable>()
 | |
|         {
 | |
|             public Serializable execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 return propertyValueDAO.getPropertyById(entityId);
 | |
|             }
 | |
|         };
 | |
|         final Serializable entityValueCheck = txnHelper.doInTransaction(getByIdCallback, false);
 | |
|         assertNotNull(entityValueCheck);
 | |
|         assertEquals(value, entityValueCheck);
 | |
|         
 | |
|         // Test the callback for multiple IDs
 | |
|         final Map<Long, Serializable> propsById = new HashMap<Long, Serializable>();
 | |
|         PropertyFinderCallback finderCallback = new PropertyFinderCallback()
 | |
|         {
 | |
|             public void handleProperty(Long id, Serializable value)
 | |
|             {
 | |
|                 propsById.put(id, value);
 | |
|             }
 | |
|         };
 | |
|         List<Long> entityIds = Collections.singletonList(entityId);
 | |
|         propertyValueDAO.getPropertiesByIds(entityIds, finderCallback);
 | |
|         
 | |
|         assertEquals("Should be exactly one value in map", 1, propsById.size());
 | |
|         assertTrue("Expected ID to be in map", propsById.containsKey(entityId));
 | |
|         assertEquals("Value was not retrieved correctly", value, propsById.get(entityId));
 | |
|         
 | |
|         // Done
 | |
|         return entityId;
 | |
|     }
 | |
| 
 | |
|     @Test
 | |
|     public void testProperty_MapOfStrings() throws Exception
 | |
|     {
 | |
|         final HashMap<String, String> map = new HashMap<String, String>(15);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String key = "MAP-KEY-" + i;
 | |
|             String value = "MAP-VALUE-" + i;
 | |
|             map.put(key, value);
 | |
|         }
 | |
|         runPropertyTest(map);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testProperty_MapOfMapOfSerializables() throws Exception
 | |
|     {
 | |
|         final HashMap<String, Serializable> mapInner = new HashMap<String, Serializable>(15);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String key = "INNERMAP-KEY-" + i;
 | |
|             Serializable value = new CompositeName("INNERMAP-VALUE-" + i);
 | |
|             mapInner.put(key, value);
 | |
|         }
 | |
|         final HashMap<String, Map<?, ?>> mapOuter = new HashMap<String, Map<?, ?>>(37);
 | |
|         for (int i = 0; i < 2; i++)
 | |
|         {
 | |
|             String key = "OUTERMAP-KEY-" + i;
 | |
|             mapOuter.put(key, mapInner);
 | |
|         }
 | |
|         runPropertyTest(mapOuter);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testProperty_MapOfMapOfStrings() throws Exception
 | |
|     {
 | |
|         final HashMap<String, String> mapInner = new HashMap<String, String>(15);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String key = "INNERMAP-KEY-" + i;
 | |
|             String value = "INNERMAP-VALUE-" + i;
 | |
|             mapInner.put(key, value);
 | |
|         }
 | |
|         final HashMap<String, Map<?, ?>> mapOuter = new HashMap<String, Map<?, ?>>(37);
 | |
|         for (int i = 0; i < 2; i++)
 | |
|         {
 | |
|             String key = "OUTERMAP-KEY-" + i;
 | |
|             mapOuter.put(key, mapInner);
 | |
|         }
 | |
|         runPropertyTest(mapOuter);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testProperty_CollectionOfStrings() throws Exception
 | |
|     {
 | |
|         final ArrayList<String> list = new ArrayList<String>(20);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String value = "COLL-VALUE-" + i;
 | |
|             list.add(value);
 | |
|         }
 | |
|         runPropertyTest(list);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testProperty_UpdateCollection() throws Exception
 | |
|     {
 | |
|         final ArrayList<String> list = new ArrayList<String>(20);
 | |
|         for (int i = 0; i < 20; i++)
 | |
|         {
 | |
|             String value = "COLL-VALUE-" + i;
 | |
|             list.add(value);
 | |
|         }
 | |
|         final Long propId = runPropertyTest(list);
 | |
|         
 | |
|         // Now update it
 | |
|         list.add("Additional value");
 | |
| 
 | |
|         RetryingTransactionCallback<Serializable> updateAndGetCallback = new RetryingTransactionCallback<Serializable>()
 | |
|         {
 | |
|             public Serializable execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 propertyValueDAO.updateProperty(propId, list);
 | |
|                 // Get it by the ID again
 | |
|                 return propertyValueDAO.getPropertyById(propId);
 | |
|             }
 | |
|         };
 | |
|         final Serializable entityValueCheck = txnHelper.doInTransaction(updateAndGetCallback, false);
 | |
|         assertNotNull(entityValueCheck);
 | |
|         assertEquals(list, entityValueCheck);
 | |
|     }
 | |
|     
 | |
| //    public void testProperty_UpdateToVersionRollover() throws Exception
 | |
| //    {
 | |
| //        final List<String> list = Collections.emptyList();
 | |
| //        final Long propId = runPropertyTest((Serializable)list);
 | |
| //        
 | |
| //        // Do 1000 updates to a property
 | |
| //        RetryingTransactionCallback<Void> updateThousandsCallback = new RetryingTransactionCallback<Void>()
 | |
| //        {
 | |
| //            public Void execute() throws Throwable
 | |
| //            {
 | |
| //                for (int i = 0; i < 1000; i++)
 | |
| //                {
 | |
| //                    propertyValueDAO.updateProperty(propId, (Serializable)list);
 | |
| //                }
 | |
| //                return null;
 | |
| //            }
 | |
| //        };
 | |
| //        for (int i = 0; i < (Short.MAX_VALUE / 1000 + 1); i++)
 | |
| //        {
 | |
| //            txnHelper.doInTransaction(updateThousandsCallback, false);
 | |
| //        }
 | |
| //    }
 | |
| //
 | |
|     @Test
 | |
|     public void testProperty_Delete() throws Exception
 | |
|     {
 | |
|         final ArrayList<String> list = new ArrayList<String>(20);
 | |
|         final Long propId = runPropertyTest(list);
 | |
|         
 | |
|         // Now delete it
 | |
|         RetryingTransactionCallback<Serializable> deleteCallback = new RetryingTransactionCallback<Serializable>()
 | |
|         {
 | |
|             public Serializable execute() throws Throwable
 | |
|             {
 | |
|                 // Get the classes
 | |
|                 propertyValueDAO.deleteProperty(propId);
 | |
|                 return null;
 | |
|             }
 | |
|         };
 | |
|         txnHelper.doInTransaction(deleteCallback, false);
 | |
| 
 | |
|         RetryingTransactionCallback<Serializable> failedGetCallback = new RetryingTransactionCallback<Serializable>()
 | |
|         {
 | |
|             public Serializable execute() throws Throwable
 | |
|             {
 | |
|                 // Get it by the ID again
 | |
|                 return propertyValueDAO.getPropertyById(propId);
 | |
|             }
 | |
|         };
 | |
|         try
 | |
|         {
 | |
|             final Serializable entityValueCheck = txnHelper.doInTransaction(failedGetCallback, false);
 | |
|             fail("Deleted property should not be gettable.  Got: " + entityValueCheck);
 | |
|         }
 | |
|         catch(Throwable e)
 | |
|         {
 | |
|             // Expected
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * Switch off caches and rerun some of the tests
 | |
|      */
 | |
|     @Test
 | |
|     public void testPropertyClass_NoCache() throws Exception
 | |
|     {
 | |
|         removeCaches();
 | |
|         testPropertyClass();
 | |
|     }
 | |
| 
 | |
|     @Test
 | |
|     public void testPropertyDateValue_NoCache() throws Exception
 | |
|     {
 | |
|         removeCaches();
 | |
|         testPropertyDateValue();
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyStringValue_NoCache() throws Exception
 | |
|     {
 | |
|         removeCaches();
 | |
|         testPropertyStringValue();
 | |
|     }
 | |
| 
 | |
|     @Test
 | |
|     public void testPropertyDoubleValue_NoCache() throws Exception
 | |
|     {
 | |
|         removeCaches();
 | |
|         testPropertyDoubleValue();
 | |
|     }
 | |
| 
 | |
|     @Test
 | |
|     public void testPropertySerializableValue_NoCache() throws Exception
 | |
|     {
 | |
|         removeCaches();
 | |
|         testPropertySerializableValue();
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyUniqueContext() throws Exception
 | |
|     {
 | |
|         final String aaa = GUID.generate();
 | |
|         final String bbb = GUID.generate();
 | |
|         
 | |
|         // Check null-null-null context
 | |
|         txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 // Get the ID for nulls
 | |
|                 Pair<Long, Long> nullPair = propertyValueDAO.getPropertyUniqueContext(null, null, null);
 | |
|                 if (nullPair != null)
 | |
|                 {
 | |
|                     propertyValueDAO.deletePropertyUniqueContext(nullPair.getFirst());
 | |
|                 }
 | |
|                 // Check nulls
 | |
|                 propertyValueDAO.createPropertyUniqueContext(null, null, null, "A VALUE");
 | |
|                 try
 | |
|                 {
 | |
|                     propertyValueDAO.createPropertyUniqueContext(null, null, null, "A VALUE");
 | |
|                     fail("Failed to throw exception creating duplicate property unique context");
 | |
|                 }
 | |
|                 catch (PropertyUniqueConstraintViolation e)
 | |
|                 {
 | |
|                     // Expected
 | |
|                 }
 | |
|                 return null;
 | |
|             }
 | |
|         }, false);
 | |
|         // Create a well-known context ID
 | |
|         final Long id = txnHelper.doInTransaction(new RetryingTransactionCallback<Long>()
 | |
|         {
 | |
|             public Long execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa, null).getFirst();
 | |
|             }
 | |
|         }, false);
 | |
|         // Check that duplicates are disallowed
 | |
|         try
 | |
|         {
 | |
|             txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|             {
 | |
|                 public Void execute() throws Throwable
 | |
|                 {
 | |
|                     propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa, null);
 | |
|                     return null;
 | |
|                 }
 | |
|             }, false);
 | |
|             fail("Failed to throw exception creating duplicate property unique context");
 | |
|         }
 | |
|         catch (PropertyUniqueConstraintViolation e)
 | |
|         {
 | |
|             // Expected
 | |
|         }
 | |
|         // Check that updates work
 | |
|         try
 | |
|         {
 | |
|             txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|             {
 | |
|                 public Void execute() throws Throwable
 | |
|                 {
 | |
|                     // Now update it
 | |
|                     propertyValueDAO.updatePropertyUniqueContextKeys(id, "A", "AA", bbb);
 | |
|                     // Should be able to create the previous one ...
 | |
|                     propertyValueDAO.createPropertyUniqueContext("A", "AA", aaa, null);
 | |
|                     // ... and fail to create the second one
 | |
|                     propertyValueDAO.createPropertyUniqueContext("A", "AA", bbb, null);
 | |
|                     return null;
 | |
|                 }
 | |
|             }, false);
 | |
|             fail("Failed to throw exception creating duplicate property unique context");
 | |
|         }
 | |
|         catch (PropertyUniqueConstraintViolation e)
 | |
|         {
 | |
|             // Expected
 | |
|         }
 | |
|         txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 // Delete
 | |
|                 propertyValueDAO.deletePropertyUniqueContext(id);
 | |
|                 propertyValueDAO.createPropertyUniqueContext("A", "AA", bbb, null);
 | |
|                 
 | |
|                 return null;
 | |
|             }
 | |
|         }, false);
 | |
|     }
 | |
|     
 | |
|     @Test
 | |
|     public void testPropertyUniqueContextValue() throws Exception
 | |
|     {
 | |
|         final String aaa = GUID.generate();
 | |
|         final String bbb = GUID.generate();
 | |
|         final String ccc = GUID.generate();
 | |
|         
 | |
|         final String v1 = GUID.generate();
 | |
|         final String v2 = GUID.generate();
 | |
|         
 | |
|         // Create a well-known context ID
 | |
|         final Long id = txnHelper.doInTransaction(new RetryingTransactionCallback<Long>()
 | |
|         {
 | |
|             public Long execute() throws Throwable
 | |
|             {
 | |
|                 return propertyValueDAO.createPropertyUniqueContext(aaa, bbb, ccc, null).getFirst();
 | |
|             }
 | |
|         }, false);
 | |
|         Pair<Long, Serializable> v0Pair = new Pair<Long, Serializable>(id, null);
 | |
|         Pair<Long, Serializable> v1Pair = new Pair<Long, Serializable>(id, v1);
 | |
|         Pair<Long, Serializable> v2Pair = new Pair<Long, Serializable>(id, v2);
 | |
|         
 | |
|         // Check, assign value and recheck
 | |
|         Pair<Long, Serializable> pair = null;
 | |
|         
 | |
|         // Check that the property is correct
 | |
|         pair = txnHelper.doInTransaction(new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 Pair<Long, Long> pair = propertyValueDAO.getPropertyUniqueContext(aaa, bbb, ccc);
 | |
|                 if (pair.getSecond() == null)
 | |
|                 {
 | |
|                     return new Pair<Long, Serializable>(pair.getFirst(), null);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Serializable value = propertyValueDAO.getPropertyById(pair.getSecond());
 | |
|                     return new Pair<Long, Serializable>(pair.getFirst(), value);
 | |
|                 }
 | |
|             }
 | |
|         }, true);
 | |
|         assertEquals("ID-value pair incorrect", v0Pair, pair);
 | |
| 
 | |
|         pair = txnHelper.doInTransaction(new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 propertyValueDAO.updatePropertyUniqueContext(aaa, bbb, ccc, v1);
 | |
|                 Pair<Long, Long> pair = propertyValueDAO.getPropertyUniqueContext(aaa, bbb, ccc);
 | |
|                 Serializable value = propertyValueDAO.getPropertyById(pair.getSecond());
 | |
|                 return new Pair<Long, Serializable>(pair.getFirst(), value);
 | |
|             }
 | |
|         }, false);
 | |
|         assertEquals("ID-value pair incorrect", v1Pair, pair);
 | |
| 
 | |
|         pair = txnHelper.doInTransaction(new RetryingTransactionCallback<Pair<Long, Serializable>>()
 | |
|         {
 | |
|             public Pair<Long, Serializable> execute() throws Throwable
 | |
|             {
 | |
|                 propertyValueDAO.updatePropertyUniqueContext(aaa, bbb, ccc, v2);
 | |
|                 Pair<Long, Long> pair = propertyValueDAO.getPropertyUniqueContext(aaa, bbb, ccc);
 | |
|                 Serializable value = propertyValueDAO.getPropertyById(pair.getSecond());
 | |
|                 return new Pair<Long, Serializable>(pair.getFirst(), value);
 | |
|             }
 | |
|         }, false);
 | |
|         assertEquals("ID-value pair incorrect", v2Pair, pair);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * MNT-10067: use a script to delete the orphaned property values.
 | |
|      */
 | |
|     @Test
 | |
|     @Ignore("The functionality is not ready, yet")
 | |
|     public void testScriptCanDeleteUnusedProps()
 | |
|     {
 | |
|         PropValGenerator valueGen = new PropValGenerator(propertyValueDAO);
 | |
|         
 | |
|         // Find some values to use in the test that aren't already in the property tables.
 | |
|         final String stringValue = valueGen.createUniqueString();
 | |
|         final Double doubleValue = valueGen.createUniqueDouble();
 | |
|         final Date dateValue = valueGen.createUniqueDate();
 | |
|         final Serializable serValue = valueGen.createUniqueSerializable();
 | |
|         // We'll keep a list of the DB IDs of the persisted values so we can later check they've been deleted.
 | |
|         final Map<Object, Long> persistedIDs = new HashMap<Object, Long>();
 | |
|         
 | |
|         txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 persistedIDs.put(stringValue, propertyValueDAO.getOrCreatePropertyStringValue(stringValue).getFirst());
 | |
|                 persistedIDs.put(doubleValue, propertyValueDAO.getOrCreatePropertyDoubleValue(doubleValue).getFirst());
 | |
|                 persistedIDs.put(dateValue, propertyValueDAO.getOrCreatePropertyDateValue(dateValue).getFirst());
 | |
|                 persistedIDs.put(serValue, propertyValueDAO.getOrCreatePropertyValue(serValue).getFirst());
 | |
|                 return null;
 | |
|             }
 | |
|         });
 | |
|         
 | |
|         // Run the clean-up script.
 | |
|         txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|         {
 | |
|             public Void execute() throws Throwable
 | |
|             {
 | |
|                 // Check there are some persisted values to delete.
 | |
|                 assertEquals(stringValue, propertyValueDAO.getPropertyStringValue(stringValue).getSecond());
 | |
|                 assertEquals(doubleValue, propertyValueDAO.getPropertyDoubleValue(doubleValue).getSecond());
 | |
|                 assertEquals(dateValue, propertyValueDAO.getPropertyDateValue(dateValue).getSecond());
 | |
|                 // Serializable values are the odd-one-out; we can't query for them by value
 | |
|                 // and no de-duplication is used during storage.
 | |
|                 assertEquals(serValue, propertyValueDAO.getPropertyValueById(persistedIDs.get(serValue)).getSecond());
 | |
|                 
 | |
|                 propertyValueDAO.cleanupUnusedValues();
 | |
|                 return null;
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         // Check all the properties have been deleted.
 | |
|         txnHelper.doInTransaction(new RetryingTransactionCallback<Void>()
 | |
|         {   
 | |
|             public Void execute() throws Throwable
 | |
|             {                
 | |
|                 assertPropDeleted(propertyValueDAO.getPropertyStringValue(stringValue));
 | |
|                 assertPropDeleted(propertyValueDAO.getPropertyDoubleValue(doubleValue));
 | |
|                 // TODO: fix date deletion, not currently handled by CleanAlfPropTables.sql
 | |
| //                assertPropDeleted(propertyValueDAO.getPropertyDateValue(dateValue));
 | |
|                 // Serializable values cannot be queried by value
 | |
|                 try
 | |
|                 {
 | |
|                     propertyValueDAO.getPropertyValueById(persistedIDs.get(serValue));
 | |
|                     fail(String.format("Persisted %s was not deleted, but should have been.",
 | |
|                                 serValue.getClass().getSimpleName()));
 | |
|                 }
 | |
|                 catch (DataIntegrityViolationException e)
 | |
|                 {
 | |
|                     // Good - it was deleted.
 | |
|                 }
 | |
|                 return null;
 | |
|             }
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     private void assertPropDeleted(Pair<Long, ?> value)
 | |
|     {
 | |
|         if (value != null)
 | |
|         {
 | |
|             String msg = String.format("Property value [%s=%s] should have been deleted by cleanup script.",
 | |
|                         value.getSecond().getClass().getSimpleName(), value.getSecond());
 | |
|             fail(msg);
 | |
|         }
 | |
|     }
 | |
| }
 |