Merged V3.2 to HEAD

17363: Fix to DbNodeServiceImple to allow restored nodes.
   17384: Minor comments
   17451: Fix ETHREEOH-2751 / ETWOONE-340 - specialising a node through an action doesn't set default values from model
   17459: ETHREEOH-2391 - Invite pending task now has lots of properties
   17465: Repo side fix for ETHREEOH-3010: Inbound and outbound Mltext multiple property are not converted correctly
   17478: Fix ETHREEOH-3340 - WCM - Revert to snapshot failure (fix AVM getListing -> AVNSync compare -> WCM revertSnapshot)
   17483: (record only) Merged V3.1 to V3.2 (record-only)
      17482: (record-only) due to earlier back-merge
   17493: Fix for ETHREEOH-3342: index.recovery.mode example is incorrect
   17494: Fix for ETHREEOH-3027: missingFullTextReindexTrigger (from index-recovery-context.xml) job does not work.
   17510: Fix for ETHREEOH-1147: Indexing large indices can lead to Java Heap space.
   17511: Fix for ETHREEOH-1271: It is possible to add one category more than one time to the same content or space
   17513: ETHREEOH_3366: Altered DictionaryDAOImpl so that passing a null QName into getType and getAspect does not result in an NPE
   17531: ETHREEOH-1186: Corrected rssfeed.get.js so a user can configure a RSS Feed dashlet that has been placed on their own dashboard
   17550: ETHREEOH-2317: Rule not fired when document has no content
   17556: Fixed ETHREEOH-1229: Can't delete space that contains "translation without content"
   17558: Fix for ETHREEOH-3356: Forms fail to persist if property or association name has an _ (underscore) in it
   17572: Changed caching of person NodeRefs so that duplicates are detected better
   17573: Fixed UTF-8 for file with encoded chars
   17576: LockAcquisitionException message specific to failed release of taken-over lock
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /alfresco/BRANCHES/V3.2:r17363,17384,17451,17459,17465,17478,17483,17493-17494,17510-17511,17513,17531,17550,17556,17558,17572-17573,17576


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18140 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-01-19 14:07:10 +00:00
parent 6b8cf8d13b
commit c67a5c18d2
28 changed files with 4343 additions and 3536 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -105,6 +105,10 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
{
public static final String NAMESPACE = "http://www.alfresco.org/test/BaseNodeServiceTest";
public static final String TEST_PREFIX = "test";
public static final String DEFAULT_VALUE = "defaultValue";
public static final String NOT_DEFAULT_VALUE = "notDefaultValue";
public static final QName TYPE_QNAME_TEST_CONTENT = QName.createQName(NAMESPACE, "content");
public static final QName TYPE_QNAME_TEST_MANY_PROPERTIES = QName.createQName(NAMESPACE, "many-properties");
public static final QName TYPE_QNAME_TEST_MANY_ML_PROPERTIES = QName.createQName(NAMESPACE, "many-ml-properties");
@@ -134,8 +138,8 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
public static final QName PROP_QNAME_LOCALE_VALUE = QName.createQName(NAMESPACE, "localeValue");
public static final QName PROP_QNAME_NULL_VALUE = QName.createQName(NAMESPACE, "nullValue");
public static final QName PROP_QNAME_MULTI_VALUE = QName.createQName(NAMESPACE, "multiValue");
public static final QName PROP_QNAME_PERIOD_VALUE = QName.createQName(NAMESPACE, "periodValue");
public static final QName PROP_QNAME_MULTI_ML_VALUE = QName.createQName(NAMESPACE, "multiMLValue");
public static final QName PROP_QNAME_PERIOD_VALUE = QName.createQName(NAMESPACE, "periodValue");
public static final QName PROP_QNAME_MULTI_ML_VALUE = QName.createQName(NAMESPACE, "multiMLValue");
public static final QName PROP_QNAME_MARKER_PROP = QName.createQName(NAMESPACE, "markerProp");
public static final QName PROP_QNAME_PROP1 = QName.createQName(NAMESPACE, "prop1");
public static final QName PROP_QNAME_PROP2 = QName.createQName(NAMESPACE, "prop2");
@@ -566,12 +570,19 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("setTypeTest"),
TYPE_QNAME_TEST_CONTENT).getChildRef();
TYPE_QNAME_TEST_CONTENT).getChildRef();
assertEquals(TYPE_QNAME_TEST_CONTENT, this.nodeService.getType(nodeRef));
assertNull(this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP1));
// Now change the type
this.nodeService.setType(nodeRef, TYPE_QNAME_EXTENDED_CONTENT);
assertEquals(TYPE_QNAME_EXTENDED_CONTENT, this.nodeService.getType(nodeRef));
assertEquals(TYPE_QNAME_EXTENDED_CONTENT, this.nodeService.getType(nodeRef));
// Check new defaults
Serializable defaultValue = this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP1);
assertNotNull("No default property value assigned", defaultValue);
assertEquals(DEFAULT_VALUE, defaultValue);
}
/**
@@ -2409,25 +2420,25 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("testDefaultValues"),
TYPE_QNAME_EXTENDED_CONTENT).getChildRef();
assertEquals("defaultValue", this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP1));
TYPE_QNAME_EXTENDED_CONTENT).getChildRef();
assertEquals(DEFAULT_VALUE, this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP1));
this.nodeService.addAspect(nodeRef, ASPECT_QNAME_WITH_DEFAULT_VALUE, null);
assertEquals("defaultValue", this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP2));
assertEquals(DEFAULT_VALUE, this.nodeService.getProperty(nodeRef, PROP_QNAME_PROP2));
// Ensure that default values do not overrite already set values
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(PROP_QNAME_PROP1, "notDefaultValue");
props.put(PROP_QNAME_PROP1, NOT_DEFAULT_VALUE);
NodeRef nodeRef2 = nodeService.createNode(
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("testDefaultValues"),
TYPE_QNAME_EXTENDED_CONTENT,
props).getChildRef();
assertEquals("notDefaultValue", this.nodeService.getProperty(nodeRef2, PROP_QNAME_PROP1));
assertEquals(NOT_DEFAULT_VALUE, this.nodeService.getProperty(nodeRef2, PROP_QNAME_PROP1));
Map<QName, Serializable> prop2 = new HashMap<QName, Serializable>(1);
prop2.put(PROP_QNAME_PROP2, "notDefaultValue");
prop2.put(PROP_QNAME_PROP2, NOT_DEFAULT_VALUE);
this.nodeService.addAspect(nodeRef2, ASPECT_QNAME_WITH_DEFAULT_VALUE, prop2);
assertEquals("notDefaultValue", this.nodeService.getProperty(nodeRef2, PROP_QNAME_PROP2));
assertEquals(NOT_DEFAULT_VALUE, this.nodeService.getProperty(nodeRef2, PROP_QNAME_PROP2));
}

View File

@@ -25,17 +25,25 @@
package org.alfresco.repo.node;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.springframework.extensions.surf.util.I18NUtil;
import javax.transaction.UserTransaction;
import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Tests the fully-intercepted version of the NodeService
@@ -245,4 +253,168 @@ public class FullNodeServiceTest extends BaseNodeServiceTest
String strValue = mlTextValue.getDefaultValue();
checkProperties.put(PROP_QNAME_ML_TEXT_VALUE, strValue);
}
@SuppressWarnings("unchecked")
public void testMultiProp() throws Exception
{
QName undeclaredPropQName = QName.createQName(NAMESPACE, getName());
// create node
NodeRef nodeRef = nodeService.createNode(
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("pathA"),
TYPE_QNAME_TEST_MULTIPLE_TESTER).getChildRef();
ArrayList<Serializable> values = new ArrayList<Serializable>(1);
values.add("ABC");
values.add("DEF");
// test allowable conditions
nodeService.setProperty(nodeRef, PROP_QNAME_STRING_PROP_SINGLE, "ABC");
// nodeService.setProperty(nodeRef, PROP_QNAME_STRING_PROP_SINGLE, values); -- should fail
nodeService.setProperty(nodeRef, PROP_QNAME_STRING_PROP_MULTIPLE, "ABC");
nodeService.setProperty(nodeRef, PROP_QNAME_STRING_PROP_MULTIPLE, values);
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_SINGLE, "ABC");
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_SINGLE, values);
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE, "ABC");
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE, values);
nodeService.setProperty(nodeRef, undeclaredPropQName, "ABC");
nodeService.setProperty(nodeRef, undeclaredPropQName, values);
// commit as we will be breaking the transaction in the next test
setComplete();
endTransaction();
UserTransaction txn = transactionService.getUserTransaction();
try
{
txn.begin();
// this should fail as we are passing multiple values into a non-any that is multiple=false
nodeService.setProperty(nodeRef, PROP_QNAME_STRING_PROP_SINGLE, values);
}
catch (DictionaryException e)
{
// expected
}
finally
{
try { txn.rollback(); } catch (Throwable e) {}
}
txn = transactionService.getUserTransaction();
try
{
txn.begin();
// Check that multi-valued d:mltext can be collections of MLText
values.clear();
values.add(new MLText("ABC"));
values.add(new MLText("DEF"));
nodeService.setProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE, values);
List<Serializable> checkValues = (List<Serializable>) nodeService.getProperty(
nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("Expected 2 MLText values back", 2, checkValues.size());
assertTrue("Incorrect type in collection", checkValues.get(0) instanceof String);
assertTrue("Incorrect type in collection", checkValues.get(1) instanceof String);
// Check that multi-valued d:any properties can be collections of collections (empty)
// We put ArrayLists and HashSets into the Collection of d:any, so that is exactly what should come out
values.clear();
ArrayList<Serializable> arrayListVal = new ArrayList<Serializable>(2);
HashSet<Serializable> hashSetVal = new HashSet<Serializable>(2);
values.add(arrayListVal);
values.add(hashSetVal);
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE, values);
checkValues = (List<Serializable>) nodeService.getProperty(
nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE);
assertEquals("Expected 2 Collection values back", 2, checkValues.size());
assertTrue("Incorrect type in collection", checkValues.get(0) instanceof ArrayList); // ArrayList in - ArrayList out
assertTrue("Incorrect type in collection", checkValues.get(1) instanceof HashSet); // HashSet in - HashSet out
// Check that multi-valued d:any properties can be collections of collections (with values)
// We put ArrayLists and HashSets into the Collection of d:any, so that is exactly what should come out
arrayListVal.add("ONE");
arrayListVal.add("TWO");
hashSetVal.add("ONE");
hashSetVal.add("TWO");
values.clear();
values.add(arrayListVal);
values.add(hashSetVal);
nodeService.setProperty(nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE, values);
checkValues = (List<Serializable>) nodeService.getProperty(
nodeRef, PROP_QNAME_ANY_PROP_MULTIPLE);
assertEquals("Expected 2 Collection values back", 2, checkValues.size());
assertTrue("Incorrect type in collection", checkValues.get(0) instanceof ArrayList); // ArrayList in - ArrayList out
assertTrue("Incorrect type in collection", checkValues.get(1) instanceof HashSet); // HashSet in - HashSet out
assertEquals("First collection incorrect", 2, ((Collection)checkValues.get(0)).size());
assertEquals("Second collection incorrect", 2, ((Collection)checkValues.get(1)).size());
}
catch (DictionaryException e)
{
// expected
}
finally
{
try { txn.rollback(); } catch (Throwable e) {}
}
}
@SuppressWarnings("unchecked")
public void testMultiValueMLTextProperties() throws Exception
{
NodeRef nodeRef = nodeService.createNode(
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("pathA"),
TYPE_QNAME_TEST_MANY_ML_PROPERTIES).getChildRef();
// Create MLText properties and add to a collection
List<MLText> mlTextCollection = new ArrayList<MLText>(2);
MLText mlText0 = new MLText();
mlText0.addValue(Locale.ENGLISH, "Hello");
mlText0.addValue(Locale.FRENCH, "Bonjour");
mlTextCollection.add(mlText0);
MLText mlText1 = new MLText();
mlText1.addValue(Locale.ENGLISH, "Bye bye");
mlText1.addValue(Locale.FRENCH, "Au revoir");
mlTextCollection.add(mlText1);
nodeService.setProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE, (Serializable) mlTextCollection);
I18NUtil.setContentLocale(Locale.ENGLISH);
Collection<String> mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Hello", "Bye bye"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.FRENCH);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Bonjour", "Au revoir"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.GERMAN);
nodeService.setProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE, (Serializable)Arrays.asList(new String[]{"eins", "zwei", "drie", "vier"}));
I18NUtil.setContentLocale(Locale.ENGLISH);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Hello", "Bye bye"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.FRENCH);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Bonjour", "Au revoir"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.GERMAN);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"eins", "zwei", "drie", "vier"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.GERMAN);
nodeService.setProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE, (Serializable)Arrays.asList(new String[]{"eins"}));
I18NUtil.setContentLocale(Locale.ENGLISH);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Hello", "Bye bye"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.FRENCH);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"Bonjour", "Au revoir"}), mlTextCollectionCheck);
I18NUtil.setContentLocale(Locale.GERMAN);
mlTextCollectionCheck = (Collection<String>) nodeService.getProperty(nodeRef, PROP_QNAME_MULTI_ML_VALUE);
assertEquals("MLText collection didn't come back correctly.", Arrays.asList(new String[]{"eins"}), mlTextCollectionCheck);
}
}

View File

@@ -25,11 +25,15 @@
package org.alfresco.repo.node;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
@@ -352,6 +356,22 @@ public class MLPropertyInterceptor implements MethodInterceptor
MLText mlText = (MLText) outboundValue;
ret = mlText.getClosestValue(contentLocale);
}
else if(isCollectionOfMLText(outboundValue))
{
Collection<?> col = (Collection<?>)outboundValue;
ArrayList<String> answer = new ArrayList<String>(col.size());
Locale closestLocale = getClosestLocale(col, contentLocale);
for(Object o : col)
{
MLText mlText = (MLText) o;
String value = mlText.get(closestLocale);
if(value != null)
{
answer.add(value);
}
}
ret = answer;
}
else if (pivotNodeRef != null) // It is an empty translation
{
if (propertyQName.equals(ContentModel.PROP_MODIFIED))
@@ -397,6 +417,58 @@ public class MLPropertyInterceptor implements MethodInterceptor
return ret;
}
public Locale getClosestLocale(Collection<?> collection, Locale locale)
{
if (collection.size() == 0)
{
return null;
}
// Use the available keys as options
HashSet<Locale> locales = new HashSet<Locale>();
for(Object o : collection)
{
MLText mlText = (MLText)o;
locales.addAll(mlText.keySet());
}
// Get a match
Locale match = I18NUtil.getNearestLocale(locale, locales);
if (match == null)
{
// No close matches for the locale - go for the default locale
locale = I18NUtil.getLocale();
match = I18NUtil.getNearestLocale(locale, locales);
if (match == null)
{
// just get any locale
match = I18NUtil.getNearestLocale(null, locales);
}
}
return match;
}
/**
* @param outboundValue
* @return
*/
private boolean isCollectionOfMLText(Serializable outboundValue)
{
if(outboundValue instanceof Collection)
{
for(Object o : (Collection<?>)outboundValue)
{
if(!(o instanceof MLText))
{
return false;
}
}
return true;
}
else
{
return false;
}
}
private Map<QName, Serializable> convertInboundProperties(
Map<QName, Serializable> currentProperties,
Map<QName, Serializable> newProperties,
@@ -443,10 +515,83 @@ public class MLPropertyInterceptor implements MethodInterceptor
else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))
{
// Don't mess with multivalued properties or instances already of type MLText
if (propertyDef.isMultiValued() || (inboundValue instanceof MLText) )
if (inboundValue instanceof MLText)
{
ret = inboundValue;
}
else if(propertyDef.isMultiValued())
{
// leave collectios of ML text alone
if(isCollectionOfMLText(inboundValue))
{
ret = inboundValue;
}
else
{
// Anything else we assume is localised
if (currentValue == null && nodeRef != null)
{
currentValue = nodeService.getProperty(nodeRef, propertyQName);
}
ArrayList<MLText> returnMLList = new ArrayList<MLText>();
if (currentValue != null)
{
Collection<MLText> currentCollection = DefaultTypeConverter.INSTANCE.getCollection(MLText.class, currentValue);
returnMLList.addAll(currentCollection);
}
Collection<String> inboundCollection = DefaultTypeConverter.INSTANCE.getCollection(String.class, inboundValue);
int count = 0;
for(String current : inboundCollection)
{
MLText newMLValue;
if(count < returnMLList.size())
{
MLText currentMLValue = returnMLList.get(count);
newMLValue = new MLText();
if (currentMLValue != null)
{
newMLValue.putAll(currentMLValue);
}
}
else
{
newMLValue = new MLText();
}
newMLValue.addValue(contentLocale, current);
if(count < returnMLList.size())
{
returnMLList.set(count, newMLValue);
}
else
{
returnMLList.add(newMLValue);
}
count++;
}
// remove locale settings for anything after
for(int i = count; i < returnMLList.size(); i++)
{
MLText currentMLValue = returnMLList.get(i);
MLText newMLValue = new MLText();
if (currentMLValue != null)
{
newMLValue.putAll(currentMLValue);
}
newMLValue.remove(contentLocale);
returnMLList.set(i, newMLValue);
}
// tidy up empty locales
ArrayList<MLText> tidy = new ArrayList<MLText>();
for(MLText mlText : returnMLList)
{
if(mlText.keySet().size() > 0)
{
tidy.add(mlText);
}
}
ret = tidy;
}
}
else
{
// This is a multilingual single-valued property

View File

@@ -28,6 +28,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.alfresco.model.ContentModel;
@@ -85,7 +86,7 @@ public class NodeRefPropertyMethodInterceptor implements MethodInterceptor
{
this.dictionaryService = dictionaryService;
}
private DictionaryService getDictionaryService()
{
return dictionaryService;
@@ -95,12 +96,12 @@ public class NodeRefPropertyMethodInterceptor implements MethodInterceptor
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
return nodeService;
}
public void init()
{
PropertyCheck.mandatory(this, "dictionaryService", dictionaryService);
@@ -302,7 +303,8 @@ public class NodeRefPropertyMethodInterceptor implements MethodInterceptor
{
if (inboundValue instanceof Collection)
{
Collection in = (Collection) inboundValue;
HashSet<NodeRef> categories = new HashSet<NodeRef>();
Collection<?> in = (Collection<?>) inboundValue;
ArrayList<NodeRef> out = new ArrayList<NodeRef>(in.size());
for (Object o : in)
{
@@ -323,7 +325,11 @@ public class NodeRefPropertyMethodInterceptor implements MethodInterceptor
QName type = getNodeService().getType(test);
if (getDictionaryService().isSubClass(type, ContentModel.TYPE_CATEGORY))
{
out.add(test);
if (!categories.contains(test))
{
out.add(test);
categories.add(test);
}
}
}
else

View File

@@ -1436,6 +1436,7 @@ public class NodeRefPropertyMethodInterceptorTest extends BaseSpringTest
ArrayList<NodeRef> values = new ArrayList<NodeRef>();
values.add(cat);
values.add(cat);
nodeService.setProperty(n1, typeCategoriesProp, values);
nodeService.setProperty(n1, typeNoderefsProp, values);
@@ -1443,19 +1444,19 @@ public class NodeRefPropertyMethodInterceptorTest extends BaseSpringTest
assertNotNull(mlAwareNodeService.getProperty(n1, typeCategoriesProp));
assertEquals(1, ((Collection) mlAwareNodeService.getProperty(n1, typeCategoriesProp)).size());
assertNotNull(mlAwareNodeService.getProperty(n1, typeNoderefsProp));
assertEquals(1, ((Collection) mlAwareNodeService.getProperty(n1, typeNoderefsProp)).size());
assertEquals(2, ((Collection) mlAwareNodeService.getProperty(n1, typeNoderefsProp)).size());
assertNotNull(mlAwareNodeService.getProperties(n1).get(typeCategoriesProp));
assertEquals(1, ((Collection) mlAwareNodeService.getProperties(n1).get(typeCategoriesProp)).size());
assertNotNull(mlAwareNodeService.getProperties(n1).get(typeNoderefsProp));
assertEquals(1, ((Collection) mlAwareNodeService.getProperties(n1).get(typeNoderefsProp)).size());
assertEquals(2, ((Collection) mlAwareNodeService.getProperties(n1).get(typeNoderefsProp)).size());
assertNotNull(nodeService.getProperty(n1, typeCategoriesProp));
assertEquals(1, ((Collection) nodeService.getProperty(n1, typeCategoriesProp)).size());
assertNotNull(nodeService.getProperty(n1, typeNoderefsProp));
assertEquals(1, ((Collection) nodeService.getProperty(n1, typeNoderefsProp)).size());
assertEquals(2, ((Collection) nodeService.getProperty(n1, typeNoderefsProp)).size());
assertNotNull(nodeService.getProperties(n1).get(typeCategoriesProp));
assertEquals(1, ((Collection) nodeService.getProperties(n1).get(typeCategoriesProp)).size());
assertNotNull(nodeService.getProperties(n1).get(typeNoderefsProp));
assertEquals(1, ((Collection) nodeService.getProperties(n1).get(typeNoderefsProp)).size());
assertEquals(2, ((Collection) nodeService.getProperties(n1).get(typeNoderefsProp)).size());
}
public void testSetPropertyMixedList()

View File

@@ -45,7 +45,6 @@ import org.alfresco.repo.node.StoreArchiveMap;
import org.alfresco.repo.node.index.NodeIndexer;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.repo.transaction.TransactionListenerAdapter;
import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
@@ -276,18 +275,20 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
properties = Collections.emptyMap();
}
// check the parent node has not been deleted in this txn
if(isDeletedNodeRef(parentRef))
{
throw new InvalidNodeRefException("The parent node has been deleted", parentRef);
}
// get/generate an ID for the node
String newUuid = generateGuid(properties);
// Remove any system properties
extractIntrinsicProperties(properties);
/**
* Check the parent node has not been deleted in this txn.
*/
if(isDeletedNodeRef(parentRef))
{
throw new InvalidNodeRefException("The parent node has been deleted", parentRef);
}
// Invoke policy behaviour
invokeBeforeCreateNode(parentRef, assocTypeQName, assocQName, nodeTypeQName);
@@ -348,6 +349,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
* now and commit!
*/
trackNewNodeRef(childAssocRef.getChildRef());
untrackDeletedNodeRef(childAssocRef.getChildRef());
// Index
nodeIndexer.indexCreateNode(childAssocRef);
@@ -393,6 +395,22 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
deletedNodes.add(deletedNodeRef);
}
/**
* Untrack a deleted node ref
*
* Used when a deleted node is restored.
*
* @param deletedNodeRef
*/
private void untrackDeletedNodeRef(NodeRef deletedNodeRef)
{
Set<NodeRef> deletedNodes = TransactionalResourceHelper.getSet(KEY_DELETED_NODES);
if (deletedNodes.size() > 0)
{
deletedNodes.remove(deletedNodeRef);
}
}
private boolean isDeletedNodeRef(NodeRef deletedNodeRef)
{
Set<NodeRef> deletedNodes = TransactionalResourceHelper.getSet(KEY_DELETED_NODES);
@@ -654,8 +672,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// Set the type
nodeDaoService.updateNode(nodePair.getFirst(), null, null, typeQName);
// Add the default aspects to the node (update the properties with any new default values)
addDefaultAspects(nodePair, typeQName);
// Add the default aspects and properties required for the given type. Existing values will not be overridden.
addDefaults(nodePair, typeQName);
// Index
nodeIndexer.indexUpdateNode(nodeRef);
@@ -936,7 +954,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
}
else
{
/**
/*
* Go ahead and archive the node
*
* Archiving will take responsibility for firing the policy behaviours on
@@ -1007,7 +1025,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
nodeDaoService.deleteNode(childNodeId);
invokeOnDeleteNode(childParentAssocRef, childNodeType, childNodeQNames, false);
// loose interest in tracking this node ref
// lose interest in tracking this node ref
untrackNewNodeRef(childNodeRef);
}
}