Merged V3.0 to HEAD

12297: Fix mysql config instructions for case sensitive user names - DOC-68
  12298: Merged V2.2 to V3.0
    12257: Fixed ETWOTWO-952: MLText properties not intercepted when calling addAspect and createNode
    12270: Fixed RhinoScriptTest to propogate exceptions for full recording by Junit
    12271: Fixed NPE in ML interceptor when null node properties are passed to createNode
    12282: Merged V2.1 to V2.2
      11616: Fix for ETWOONE-218: Common.js function needs to be changed to support root context
    12287: Merged V2.1 to V2.2
      12229: WCM - disable/hide link validation by defrault (ETWOONE-106, ETWOONE-392)
  12301: Merged V2.2 to V3.0
    12288: Merged V2.1 to V2.2
      12233: Fixed ETWOONE-124: Add the property UUIDBinding to ImporterBootstrap


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12530 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2008-12-22 12:17:00 +00:00
parent eca46db62b
commit 38ba58dede
9 changed files with 284 additions and 69 deletions

View File

@@ -266,7 +266,16 @@
<!-- Poll interval to check getLatestSnapshotID (in milliseconds). --> <!-- Poll interval to check getLatestSnapshotID (in milliseconds). -->
<!-- Note: If pollInterval is 0, link validation is disabled. --> <!-- Note: If pollInterval is 0, link validation is disabled. -->
<property name="pollInterval" value="5000"/> <property name="pollInterval">
<value>${linkvalidation.pollInterval}</value>
</property>
<property name="retryInterval">
<value>${linkvalidation.retryInterval}</value>
</property>
<property name="disableOnFail">
<value>${linkvalidation.disableOnFail}</value>
</property>
<!-- Timeouts (in milliseconds) --> <!-- Timeouts (in milliseconds) -->
<property name="localConnectTimeout" value="10000"/> <property name="localConnectTimeout" value="10000"/>

View File

@@ -226,21 +226,29 @@ system.people_container.childname=sys:people
system.workflow_container.childname=sys:workflow system.workflow_container.childname=sys:workflow
# Are user names case sensitive? # Are user names case sensitive?
# ==============================
#
# NOTE: If you are using mysql you must have case sensitive collation
#
# You can do this when creating the alfresco database at the start
# CREATE DATABASE alfresco CHARACTER SET utf8 COLLATE utf8_bin;
# If you want to do this later this is a dump and load fix as it is done when the database, tables and columns are created.
#
# Must other databases are case sensitive by default.
#
user.name.caseSensitive=false user.name.caseSensitive=false
# AVM Specific properties. # AVM Specific properties.
avm.remote.idlestream.timeout=30000 avm.remote.idlestream.timeout=30000
# ################################## #
# WCM Link Validation Configuration #
# ################################## #
#
# Note: Link Validation is disabled by default (as per poll interval = 0)
#
# linkvalidation.pollInterval - Poll interval to check getLatestSnapshotID (in milliseconds), eg. 5000 for 5 sec interval
# If pollInterval is 0, link validation is disabled.
#
# linkvalidation.retryInterval - Retry interval (Virtualization server is not accessible or an error has occurred
# during link validation.
#
# linkvalidation.disableOnFail - If set to TRUE link validation service will be terminated if an error will be occurred.
linkvalidation.pollInterval=0
linkvalidation.retryInterval=120000
linkvalidation.disableOnFail=false
# ECM content usages/quotas # ECM content usages/quotas
system.usages.enabled=true system.usages.enabled=true

View File

@@ -83,9 +83,10 @@ public class ImporterBootstrap extends AbstractLifecycleBean
private static final Log logger = LogFactory.getLog(ImporterBootstrap.class); private static final Log logger = LogFactory.getLog(ImporterBootstrap.class);
private boolean logEnabled = false; private boolean logEnabled = false;
// Dependencies
private boolean allowWrite = true; private boolean allowWrite = true;
private boolean useExistingStore = false; private boolean useExistingStore = false;
private UUID_BINDING uuidBinding = null;
// Dependencies
private TransactionService transactionService; private TransactionService transactionService;
private NamespaceService namespaceService; private NamespaceService namespaceService;
private NodeService nodeService; private NodeService nodeService;
@@ -125,6 +126,19 @@ public class ImporterBootstrap extends AbstractLifecycleBean
this.useExistingStore = useExistingStore; this.useExistingStore = useExistingStore;
} }
/**
* Set the behaviour for generating UUIDs in the import. Values are set by the
* {@link UUID_BINDING} enum and default to {@link UUID_BINDING#CREATE_NEW_WITH_UUID}.
* <p/>
* This setting overrides the UUID binding behaviour specified in the view properties.
*
* @param uuidBinding the UUID generation behaviour
*/
public void setUuidBinding(UUID_BINDING uuidBinding)
{
this.uuidBinding = uuidBinding;
}
/** /**
* Sets the Transaction Service * Sets the Transaction Service
* *
@@ -420,18 +434,23 @@ public class ImporterBootstrap extends AbstractLifecycleBean
binding.setResourceBundle(bundle); binding.setResourceBundle(bundle);
} }
String uuidBinding = bootstrapView.getProperty(VIEW_UUID_BINDING); String viewUuidBinding = bootstrapView.getProperty(VIEW_UUID_BINDING);
if (uuidBinding != null && uuidBinding.length() > 0) if (viewUuidBinding != null && viewUuidBinding.length() > 0)
{ {
try try
{ {
binding.setUUIDBinding(UUID_BINDING.valueOf(UUID_BINDING.class, uuidBinding)); binding.setUUIDBinding(UUID_BINDING.valueOf(UUID_BINDING.class, viewUuidBinding));
} }
catch(IllegalArgumentException e) catch(IllegalArgumentException e)
{ {
throw new ImporterException("The value " + uuidBinding + " is an invalid uuidBinding"); throw new ImporterException("The value " + viewUuidBinding + " is an invalid uuidBinding");
} }
} }
// Override the UUID binding with the bean's
if (this.uuidBinding != null)
{
binding.setUUIDBinding(this.uuidBinding);
}
// Now import... // Now import...
ImporterProgress importProgress = null; ImporterProgress importProgress = null;
@@ -539,14 +558,13 @@ public class ImporterBootstrap extends AbstractLifecycleBean
private Properties configuration = null; private Properties configuration = null;
private ResourceBundle resourceBundle = null; private ResourceBundle resourceBundle = null;
private Location bootstrapLocation = null; private Location bootstrapLocation = null;
/** by default, use create new strategy for bootstrap import */
private UUID_BINDING uuidBinding = UUID_BINDING.CREATE_NEW_WITH_UUID;
private static final String IMPORT_LOCATION_UUID = "bootstrap.location.uuid"; private static final String IMPORT_LOCATION_UUID = "bootstrap.location.uuid";
private static final String IMPORT_LOCATION_NODEREF = "bootstrap.location.noderef"; private static final String IMPORT_LOCATION_NODEREF = "bootstrap.location.noderef";
private static final String IMPORT_LOCATION_PATH = "bootstrap.location.path"; private static final String IMPORT_LOCATION_PATH = "bootstrap.location.path";
// by default, use create new strategy for bootstrap import
private UUID_BINDING uuidBinding = UUID_BINDING.CREATE_NEW_WITH_UUID;
/** /**
* Set Import Configuration * Set Import Configuration
* *
@@ -620,10 +638,6 @@ public class ImporterBootstrap extends AbstractLifecycleBean
return value; return value;
} }
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ImporterBinding#getUUIDBinding()
*/
public UUID_BINDING getUUIDBinding() public UUID_BINDING getUUIDBinding()
{ {
return uuidBinding; return uuidBinding;
@@ -639,19 +653,11 @@ public class ImporterBootstrap extends AbstractLifecycleBean
this.uuidBinding = uuidBinding; this.uuidBinding = uuidBinding;
} }
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ImporterBinding#searchWithinTransaction()
*/
public boolean allowReferenceWithinTransaction() public boolean allowReferenceWithinTransaction()
{ {
return true; return true;
} }
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ImporterBinding#getExcludedClasses()
*/
public QName[] getExcludedClasses() public QName[] getExcludedClasses()
{ {
// Note: Do not exclude any classes, we want to import all // Note: Do not exclude any classes, we want to import all

View File

@@ -33,6 +33,7 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.view.ImporterService; import org.alfresco.service.cmr.view.ImporterService;
import org.alfresco.service.cmr.view.Location; import org.alfresco.service.cmr.view.Location;
import org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING;
import org.alfresco.util.BaseSpringTest; import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.debug.NodeStoreInspector; import org.alfresco.util.debug.NodeStoreInspector;
@@ -80,6 +81,54 @@ public class ImporterComponentTest extends BaseSpringTest
System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef)); System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef));
} }
public void testImportWithUuidBinding() throws Exception
{
Location location = new Location(storeRef);
// First pass must succeed
InputStream test1 = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml");
InputStreamReader testReader1 = new InputStreamReader(test1, "UTF-8");
try
{
importerService.importView(testReader1, location, null, new ImportTimerProgress());
}
finally
{
testReader1.close();
}
// Second pass must succeed (defaults to CREATE_NEW)
InputStream test2 = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml");
InputStreamReader testReader2 = new InputStreamReader(test2, "UTF-8");
try
{
importerBootstrap.setUuidBinding(UUID_BINDING.CREATE_NEW_WITH_UUID);
importerService.importView(testReader2, location, null, new ImportTimerProgress());
}
finally
{
testReader2.close();
}
// Set the UUID binding to guarantee a failure
InputStream test3 = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml");
InputStreamReader testReader3 = new InputStreamReader(test3, "UTF-8");
try
{
importerBootstrap.setUuidBinding(UUID_BINDING.THROW_ON_COLLISION);
importerService.importView(testReader3, location, null, new ImportTimerProgress());
fail("Failed to detected collision of UUID on import with THROW_ON_COLLISION");
}
catch (Throwable e)
{
// Expected
}
finally
{
importerBootstrap.setUuidBinding(UUID_BINDING.CREATE_NEW_WITH_UUID);
testReader3.close();
}
System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef));
}
public void testBootstrap() public void testBootstrap()
{ {
StoreRef bootstrapStoreRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); StoreRef bootstrapStoreRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());

View File

@@ -22,6 +22,7 @@
<cm:auditable/> <cm:auditable/>
</view:aspects> </view:aspects>
<view:properties> <view:properties>
<sys:node-uuid>05efa5db-2817-4ada-a0dc-657db2b2a0ac</sys:node-uuid>
<cm:name>`¬¦!£$%^&amp;()-_=+tnu0000[]{};'#@~,</cm:name> <cm:name>`¬¦!£$%^&amp;()-_=+tnu0000[]{};'#@~,</cm:name>
<cm:creator>testuser</cm:creator> <cm:creator>testuser</cm:creator>
<cm:modifier>testuser</cm:modifier> <cm:modifier>testuser</cm:modifier>

View File

@@ -141,16 +141,11 @@ public class RhinoScriptTest extends TestCase
// try another script eval - this time a function call returning a result // try another script eval - this time a function call returning a result
result = cx.evaluateString(scope, "function f(x) {return x+1} f(7)", "TestJS2", 1, null); result = cx.evaluateString(scope, "function f(x) {return x+1} f(7)", "TestJS2", 1, null);
assertEquals(8.0, cx.toNumber(result)); assertEquals(8.0, Context.toNumber(result));
}
catch (Throwable err)
{
err.printStackTrace();
fail(err.getMessage());
} }
finally finally
{ {
cx.exit(); Context.exit();
} }
return null; return null;
@@ -186,7 +181,7 @@ public class RhinoScriptTest extends TestCase
// evaluate script that touches the wrapped NodeRef // evaluate script that touches the wrapped NodeRef
Object result = cx.evaluateString(scope, "obj = rootref.getId()", "TestJS3", 1, null); Object result = cx.evaluateString(scope, "obj = rootref.getId()", "TestJS3", 1, null);
assertEquals(ref1.getId(), cx.toString(result)); assertEquals(ref1.getId(), Context.toString(result));
// wrap a scriptable Alfresco Node object - the Node object is a wrapper like TemplateNode // wrap a scriptable Alfresco Node object - the Node object is a wrapper like TemplateNode
ScriptNode node1 = new ScriptNode(root, serviceRegistry, scope); ScriptNode node1 = new ScriptNode(root, serviceRegistry, scope);
@@ -196,14 +191,9 @@ public class RhinoScriptTest extends TestCase
// evaluate scripts that perform methods on the wrapped Node // evaluate scripts that perform methods on the wrapped Node
result = cx.evaluateString(scope, TESTSCRIPT1, "TestJS4", 1, null); result = cx.evaluateString(scope, TESTSCRIPT1, "TestJS4", 1, null);
} }
catch (Throwable err)
{
err.printStackTrace();
fail(err.getMessage());
}
finally finally
{ {
cx.exit(); Context.exit();
} }
return null; return null;
@@ -258,10 +248,8 @@ public class RhinoScriptTest extends TestCase
// test executing a script directly as a String // test executing a script directly as a String
scriptService.executeScriptString("javascript", TESTSCRIPT1, model); scriptService.executeScriptString("javascript", TESTSCRIPT1, model);
} }
catch (Throwable err) finally
{ {
err.printStackTrace();
fail(err.getMessage());
} }
return null; return null;
@@ -311,10 +299,8 @@ public class RhinoScriptTest extends TestCase
// ensure aspect has been added via script // ensure aspect has been added via script
assertTrue(nodeService.hasAspect(childRef.getChildRef(), ContentModel.ASPECT_LOCKABLE)); assertTrue(nodeService.hasAspect(childRef.getChildRef(), ContentModel.ASPECT_LOCKABLE));
} }
catch (Throwable err) finally
{ {
err.printStackTrace();
fail(err.getMessage());
} }
return null; return null;
@@ -361,10 +347,8 @@ public class RhinoScriptTest extends TestCase
System.out.println("Result from TESTSCRIPT_CLASSPATH3: " + result.toString()); System.out.println("Result from TESTSCRIPT_CLASSPATH3: " + result.toString());
assertTrue((Boolean)result); // we know the result is a boolean assertTrue((Boolean)result); // we know the result is a boolean
} }
catch (Throwable err) finally
{ {
err.printStackTrace();
fail(err.getMessage());
} }
return null; return null;

View File

@@ -588,6 +588,26 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
{ {
value = new ContentData(null, MimetypeMap.EXTENSION_BINARY, 0L, "UTF-8"); value = new ContentData(null, MimetypeMap.EXTENSION_BINARY, 0L, "UTF-8");
} }
else if (propertyTypeQName.equals(DataTypeDefinition.LOCALE))
{
value = Locale.CHINESE;
}
else if (propertyTypeQName.equals(DataTypeDefinition.BOOLEAN))
{
value = Boolean.TRUE;
}
else if (propertyTypeQName.equals(DataTypeDefinition.PATH))
{
value = new Path();
}
else if (propertyTypeQName.equals(DataTypeDefinition.QNAME))
{
value = TYPE_QNAME_EXTENDED_CONTENT;
}
else if (propertyTypeQName.equals(DataTypeDefinition.CATEGORY) || propertyTypeQName.equals(DataTypeDefinition.NODE_REF))
{
value = new NodeRef("workspace://SpacesStore/12345");
}
else else
{ {
value = new Long(System.currentTimeMillis()); value = new Long(System.currentTimeMillis());

View File

@@ -25,11 +25,14 @@
package org.alfresco.repo.node; package org.alfresco.repo.node;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.node.db.DbNodeServiceImpl; import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.service.cmr.repository.MLText; 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.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
@@ -132,6 +135,75 @@ public class FullNodeServiceTest extends BaseNodeServiceTest
assertNull("Value returned is not null", mlText); assertNull("Value returned is not null", mlText);
} }
public void testMLValuesOnCreate() throws Exception
{
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
fillProperties(BaseNodeServiceTest.TYPE_QNAME_TEST_MANY_PROPERTIES, properties);
// Replace the MLText value with a plain string
properties.put(BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE, "Bonjour");
// Now switch to French
I18NUtil.setContentLocale(Locale.FRENCH);
// Create a node with the value
NodeRef nodeRef = nodeService.createNode(
rootNodeRef,
BaseNodeServiceTest.ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName(BaseNodeServiceTest.NAMESPACE, getName()),
BaseNodeServiceTest.TYPE_QNAME_TEST_MANY_PROPERTIES,
properties).getChildRef();
// Now switch to English
I18NUtil.setContentLocale(Locale.ENGLISH);
// Set the english property
nodeService.setProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE, "Hello");
// Switch back to French and get the value
I18NUtil.setContentLocale(Locale.FRENCH);
assertEquals(
"Expected French value property",
"Bonjour",
nodeService.getProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
// Switch back to English and get the value
I18NUtil.setContentLocale(Locale.ENGLISH);
assertEquals(
"Expected English value property",
"Hello",
nodeService.getProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
}
public void testMLValuesOnAddAspect() throws Exception
{
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
fillProperties(BaseNodeServiceTest.TYPE_QNAME_TEST_MANY_PROPERTIES, properties);
// Replace the MLText value with a plain string
properties.put(BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE, "Bonjour");
// Now switch to French
I18NUtil.setContentLocale(Locale.FRENCH);
// Add an aspect
NodeRef nodeRef = rootNodeRef;
nodeService.addAspect(
nodeRef,
BaseNodeServiceTest.ASPECT_QNAME_TEST_TITLED,
properties);
// Now switch to English
I18NUtil.setContentLocale(Locale.ENGLISH);
// Set the english property
nodeService.setProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE, "Hello");
// Switch back to French and get the value
I18NUtil.setContentLocale(Locale.FRENCH);
assertEquals(
"Expected French value property",
"Bonjour",
nodeService.getProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
// Switch back to English and get the value
I18NUtil.setContentLocale(Locale.ENGLISH);
assertEquals(
"Expected English value property",
"Hello",
nodeService.getProperty(nodeRef, BaseNodeServiceTest.PROP_QNAME_ML_TEXT_VALUE));
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@@ -25,6 +25,7 @@
package org.alfresco.repo.node; package org.alfresco.repo.node;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@@ -196,26 +197,20 @@ public class MLPropertyInterceptor implements MethodInterceptor
else if (methodName.equals("setProperties")) else if (methodName.equals("setProperties"))
{ {
NodeRef nodeRef = (NodeRef) args[0]; NodeRef nodeRef = (NodeRef) args[0];
Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[1];
// Get the pivot translation, if appropriate // Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef); NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[1];
// Get the current properties for the node // Get the current properties for the node
Map<QName, Serializable> currentProperties = nodeService.getProperties(nodeRef); Map<QName, Serializable> currentProperties = nodeService.getProperties(nodeRef);
// Convert all properties // Convert all properties
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(newProperties.size() * 2); Map<QName, Serializable> convertedProperties = convertInboundProperties(
for (Map.Entry<QName, Serializable> entry : newProperties.entrySet()) currentProperties,
{ newProperties,
QName propertyQName = entry.getKey(); contentLocale,
Serializable inboundValue = entry.getValue(); nodeRef,
// Get the current property value pivotNodeRef);
Serializable currentValue = currentProperties.get(propertyQName);
// Convert the inbound property value
inboundValue = convertInboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, inboundValue, currentValue);
// Put the value into the map
convertedProperties.put(propertyQName, inboundValue);
}
// Now complete the call by passing the converted properties // Now complete the call by passing the converted properties
nodeService.setProperties(nodeRef, convertedProperties); nodeService.setProperties(nodeRef, convertedProperties);
// Done // Done
@@ -236,6 +231,55 @@ public class MLPropertyInterceptor implements MethodInterceptor
nodeService.setProperty(nodeRef, propertyQName, inboundValue); nodeService.setProperty(nodeRef, propertyQName, inboundValue);
// Done // Done
} }
else if (methodName.equals("createNode") && args.length > 4)
{
NodeRef parentNodeRef = (NodeRef) args[0];
QName assocTypeQName = (QName) args[1];
QName assocQName = (QName) args[2];
QName nodeTypeQName = (QName) args[3];
Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[4];
if (newProperties == null)
{
newProperties = Collections.emptyMap();
}
NodeRef nodeRef = null; // Not created yet
// No pivot
NodeRef pivotNodeRef = null;
// Convert all properties
Map<QName, Serializable> convertedProperties = convertInboundProperties(
null,
newProperties,
contentLocale,
nodeRef,
pivotNodeRef);
// Now complete the call by passing the converted properties
ret = nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, convertedProperties);
// Done
}
else if (methodName.equals("addAspect") && args[2] != null)
{
NodeRef nodeRef = (NodeRef) args[0];
QName aspectTypeQName = (QName) args[1];
// Get the pivot translation, if appropriate
NodeRef pivotNodeRef = getPivotNodeRef(nodeRef);
Map<QName, Serializable> newProperties =(Map<QName, Serializable>) args[2];
// Get the current properties for the node
Map<QName, Serializable> currentProperties = nodeService.getProperties(nodeRef);
// Convert all properties
Map<QName, Serializable> convertedProperties = convertInboundProperties(
currentProperties,
newProperties,
contentLocale,
nodeRef,
pivotNodeRef);
// Now complete the call by passing the converted properties
nodeService.addAspect(nodeRef, aspectTypeQName, convertedProperties);
// Done
}
else else
{ {
ret = invocation.proceed(); ret = invocation.proceed();
@@ -328,6 +372,28 @@ public class MLPropertyInterceptor implements MethodInterceptor
return ret; return ret;
} }
private Map<QName, Serializable> convertInboundProperties(
Map<QName, Serializable> currentProperties,
Map<QName, Serializable> newProperties,
Locale contentLocale,
NodeRef nodeRef,
NodeRef pivotNodeRef)
{
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(newProperties.size() * 2);
for (Map.Entry<QName, Serializable> entry : newProperties.entrySet())
{
QName propertyQName = entry.getKey();
Serializable inboundValue = entry.getValue();
// Get the current property value
Serializable currentValue = currentProperties == null ? null : currentProperties.get(propertyQName);
// Convert the inbound property value
inboundValue = convertInboundProperty(contentLocale, nodeRef, pivotNodeRef, propertyQName, inboundValue, currentValue);
// Put the value into the map
convertedProperties.put(propertyQName, inboundValue);
}
return convertedProperties;
}
/** /**
* *
* @param inboundValue The value that must be set * @param inboundValue The value that must be set
@@ -360,7 +426,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
{ {
// This is a multilingual single-valued property // This is a multilingual single-valued property
// Get the current value from the node service, if not provided // Get the current value from the node service, if not provided
if (currentValue == null) if (currentValue == null && nodeRef != null)
{ {
currentValue = nodeService.getProperty(nodeRef, propertyQName); currentValue = nodeService.getProperty(nodeRef, propertyQName);
} }