mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
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:
@@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user