mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Adding new files missed yesterday from merge of re-factored form.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21155 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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.forms.processor.workflow;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public class DataKeyInfo
|
||||
{
|
||||
private final String dataKey;
|
||||
private final QName qName;
|
||||
private final FieldType fieldType;
|
||||
private final boolean isAdd;
|
||||
|
||||
private DataKeyInfo(String dataKey, QName qName, FieldType fieldType, boolean isAdd)
|
||||
{
|
||||
this.dataKey = dataKey;
|
||||
this.qName = qName;
|
||||
this.fieldType = fieldType;
|
||||
this.isAdd = isAdd;
|
||||
}
|
||||
|
||||
public static DataKeyInfo makeAssociationDataKeyInfo(String dataKey, QName qName, boolean isAdd)
|
||||
{
|
||||
return new DataKeyInfo(dataKey, qName, FieldType.ASSOCIATION, isAdd);
|
||||
}
|
||||
|
||||
public static DataKeyInfo makePropertyDataKeyInfo(String dataKey, QName qName)
|
||||
{
|
||||
return new DataKeyInfo(dataKey, qName, FieldType.PROPERTY, true);
|
||||
}
|
||||
|
||||
public static DataKeyInfo makeTransientDataKeyInfo(String dataKey)
|
||||
{
|
||||
return new DataKeyInfo(dataKey, null, FieldType.TRANSIENT, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dataKey
|
||||
*/
|
||||
public String getDataKey()
|
||||
{
|
||||
return dataKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the qName
|
||||
*/
|
||||
public QName getqName()
|
||||
{
|
||||
return qName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the fieldType
|
||||
*/
|
||||
public FieldType getFieldType()
|
||||
{
|
||||
return fieldType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isAdd
|
||||
*/
|
||||
public boolean isAdd()
|
||||
{
|
||||
return isAdd;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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.forms.processor.workflow;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
import static org.alfresco.repo.forms.processor.node.FormFieldConstants.*;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public class DataKeyMatcher
|
||||
{
|
||||
/**
|
||||
* A regular expression which can be used to match property names. These
|
||||
* names will look like <code>"prop_cm_name"</code>. The pattern can also be
|
||||
* used to extract the "cm" and the "name" parts.
|
||||
*/
|
||||
private final static Pattern propertyNamePattern = Pattern.compile("(^[a-zA-Z0-9]+)_([a-zA-Z0-9_]+$)");
|
||||
|
||||
public DataKeyMatcher(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* A regular expression which can be used to match association names. These
|
||||
* names will look like <code>"assoc_cm_references_added"</code>. The
|
||||
* pattern can also be used to extract the "cm", the "name" and the suffix
|
||||
* parts.
|
||||
*/
|
||||
private final static Pattern associationNamePattern = Pattern.compile("(^[a-zA-Z0-9]+)_([a-zA-Z0-9_]+)(_[a-zA-Z]+$)");
|
||||
|
||||
private final NamespaceService namespaceService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dataKey
|
||||
* @return
|
||||
*/
|
||||
public DataKeyInfo match(String dataKey)
|
||||
{
|
||||
if (dataKey.startsWith(PROP_DATA_PREFIX))
|
||||
{
|
||||
return matchProperty(dataKey);
|
||||
}
|
||||
else if(dataKey.startsWith(ASSOC_DATA_PREFIX))
|
||||
{
|
||||
return matchAssociation(dataKey);
|
||||
}
|
||||
|
||||
// No match found.
|
||||
return null;
|
||||
}
|
||||
|
||||
private DataKeyInfo matchAssociation(String dataKey)
|
||||
{
|
||||
String keyName = dataKey.substring(ASSOC_DATA_PREFIX.length());
|
||||
Matcher matcher = associationNamePattern.matcher(keyName);
|
||||
if (!matcher.matches())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
QName qName = getQName(matcher);
|
||||
String suffix = matcher.group(3);
|
||||
boolean isAdd = !(ASSOC_DATA_REMOVED_SUFFIX.equals(suffix));
|
||||
return DataKeyInfo.makeAssociationDataKeyInfo(keyName, qName, isAdd);
|
||||
}
|
||||
|
||||
private DataKeyInfo matchProperty(String dataKey)
|
||||
{
|
||||
String keyName = dataKey.substring(PROP_DATA_PREFIX.length());
|
||||
Matcher matcher = propertyNamePattern.matcher(keyName);
|
||||
if (matcher.matches())
|
||||
{
|
||||
QName qName = getQName(matcher);
|
||||
return DataKeyInfo.makePropertyDataKeyInfo(keyName, qName);
|
||||
}
|
||||
return DataKeyInfo.makeTransientDataKeyInfo(keyName);
|
||||
}
|
||||
|
||||
private QName getQName(Matcher matcher)
|
||||
{
|
||||
String prefix = matcher.group(1);
|
||||
String localName = matcher.group(2);
|
||||
QName qName = QName.createQName(prefix, localName, namespaceService);
|
||||
return qName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 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.forms.processor.workflow;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*
|
||||
*/
|
||||
public enum FieldType
|
||||
{
|
||||
ASSOCIATION,
|
||||
PROPERTY,
|
||||
TRANSIENT;
|
||||
}
|
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
import org.alfresco.repo.forms.FormData.FieldData;
|
||||
import org.alfresco.repo.forms.processor.FieldProcessorRegistry;
|
||||
import org.alfresco.repo.forms.processor.node.ContentModelFormProcessor;
|
||||
import org.alfresco.repo.forms.processor.node.ItemData;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*/
|
||||
public class TaskFormProcessor extends ContentModelFormProcessor<WorkflowTask, WorkflowTask>
|
||||
{
|
||||
/** Logger */
|
||||
private static final Log LOGGER = LogFactory.getLog(TaskFormProcessor.class);
|
||||
private static final TypedPropertyValueGetter valueGetter = new TypedPropertyValueGetter();
|
||||
|
||||
private DataKeyMatcher keyMatcher;
|
||||
private WorkflowService workflowService;
|
||||
|
||||
// Constructor for Spring
|
||||
public TaskFormProcessor()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
// Constructor for tests.
|
||||
public TaskFormProcessor(WorkflowService workflowService, NamespaceService namespaceService,
|
||||
DictionaryService dictionaryService, FieldProcessorRegistry fieldProcessorRegistry)
|
||||
{
|
||||
this.workflowService = workflowService;
|
||||
this.namespaceService = namespaceService;
|
||||
this.dictionaryService = dictionaryService;
|
||||
this.fieldProcessorRegistry = fieldProcessorRegistry;
|
||||
this.keyMatcher = new DataKeyMatcher(namespaceService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WorkflowTask getTypedItem(Item item)
|
||||
{
|
||||
ParameterCheck.mandatory("item", item);
|
||||
String id = item.getId();
|
||||
WorkflowTask task = workflowService.getTaskById(id);
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WorkflowTask internalPersist(WorkflowTask task, FormData data)
|
||||
{
|
||||
TaskUpdater updater = new TaskUpdater(task.id, workflowService);
|
||||
ItemData<WorkflowTask> itemData = makeItemData(task);
|
||||
for (FieldData fieldData : data)
|
||||
{
|
||||
addFieldToSerialize(updater, itemData, fieldData);
|
||||
}
|
||||
return updater.update();
|
||||
}
|
||||
|
||||
private void addFieldToSerialize(TaskUpdater updater,
|
||||
ItemData<?> itemData,
|
||||
FieldData fieldData)
|
||||
{
|
||||
String name = fieldData.getName();
|
||||
DataKeyInfo keyInfo = keyMatcher.match(name);
|
||||
if ((keyInfo == null || FieldType.TRANSIENT == keyInfo.getFieldType()) &&
|
||||
LOGGER.isWarnEnabled())
|
||||
{
|
||||
LOGGER.warn("Ignoring unrecognized field: " + name);
|
||||
}
|
||||
|
||||
if (keyInfo != null)
|
||||
{
|
||||
QName fullName = keyInfo.getqName();
|
||||
Object rawValue = fieldData.getValue();
|
||||
if (FieldType.PROPERTY == keyInfo.getFieldType())
|
||||
{
|
||||
Serializable propValue = getPropertyValueToPersist(fullName, rawValue, itemData);
|
||||
// TODO What if the user wants to set prop to null?
|
||||
if (propValue != null)
|
||||
{
|
||||
updater.addProperty(fullName, propValue);
|
||||
}
|
||||
}
|
||||
else if (FieldType.ASSOCIATION == keyInfo.getFieldType())
|
||||
{
|
||||
if (rawValue instanceof String)
|
||||
{
|
||||
updater.changeAssociation(fullName, (String) rawValue, keyInfo.isAdd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Serializable getPropertyValueToPersist(QName fullName,
|
||||
Object value,
|
||||
ItemData<?> itemData)
|
||||
{
|
||||
PropertyDefinition propDef = itemData.getPropertyDefinition(fullName);
|
||||
if (propDef == null)
|
||||
{
|
||||
propDef = dictionaryService.getProperty(fullName);
|
||||
}
|
||||
if (propDef != null)
|
||||
{
|
||||
return valueGetter.getValue(value, propDef);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemType(java
|
||||
* .lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected String getItemType(WorkflowTask item)
|
||||
{
|
||||
TypeDefinition typeDef = item.definition.metadata;
|
||||
return typeDef.getName().toPrefixString(namespaceService);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.FilteredFormProcessor#getItemURI(java
|
||||
* .lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected String getItemURI(WorkflowTask item)
|
||||
{
|
||||
// TODO Check this URL is OK.
|
||||
return "/api/task-instances/" + item.id;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see
|
||||
* org.alfresco.repo.forms.processor.task.ContentModelFormProcessor#getLogger
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
protected Log getLogger()
|
||||
{
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TypeDefinition getBaseType(WorkflowTask task)
|
||||
{
|
||||
return task.definition.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<QName, Serializable> getPropertyValues(WorkflowTask task)
|
||||
{
|
||||
return task.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<QName, Serializable> getAssociationValues(WorkflowTask item)
|
||||
{
|
||||
return item.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> getTransientValues(WorkflowTask item)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Workflow Service.
|
||||
*
|
||||
* @param workflowService
|
||||
*/
|
||||
public void setWorkflowService(WorkflowService workflowService)
|
||||
{
|
||||
this.workflowService = workflowService;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seeorg.alfresco.repo.forms.processor.task.ContentModelFormProcessor#
|
||||
* setNamespaceService(org.alfresco.service.namespace.NamespaceService)
|
||||
*/
|
||||
@Override
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
super.setNamespaceService(namespaceService);
|
||||
this.keyMatcher = new DataKeyMatcher(namespaceService);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyMap;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.repo.forms.FieldDefinition;
|
||||
import org.alfresco.repo.forms.Form;
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
import org.alfresco.repo.forms.FormData.FieldData;
|
||||
import org.alfresco.repo.forms.processor.node.DefaultFieldProcessor;
|
||||
import org.alfresco.repo.forms.processor.node.FormFieldConstants;
|
||||
import org.alfresco.repo.forms.processor.node.MockClassAttributeDefinition;
|
||||
import org.alfresco.repo.forms.processor.node.MockFieldProcessorRegistry;
|
||||
import org.alfresco.repo.workflow.WorkflowModel;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowException;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowNode;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskState;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.NamespaceServiceMemoryImpl;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*/
|
||||
public class TaskFormProcessorTest extends TestCase
|
||||
{
|
||||
private static final String TASK_DEF_NAME = "TaskDef";
|
||||
private static final String TASK_ID = "Real Id";
|
||||
private static final QName DESC_NAME = WorkflowModel.PROP_DESCRIPTION;
|
||||
private static final QName STATUS_NAME = WorkflowModel.PROP_STATUS;
|
||||
private static final QName PROP_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_prop");
|
||||
private static final QName ACTORS_NAME = WorkflowModel.ASSOC_POOLED_ACTORS;
|
||||
private static final QName ASSIGNEE_NAME = WorkflowModel.ASSOC_ASSIGNEE;
|
||||
private static final QName ASSOC_WITH_ = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "some_assoc");
|
||||
private static final NodeRef FAKE_NODE = new NodeRef(NamespaceService.BPM_MODEL_1_0_URI + "/FakeNode");
|
||||
|
||||
private WorkflowService workflowService;
|
||||
private TaskFormProcessor processor;
|
||||
private WorkflowTask task;
|
||||
private NamespaceService namespaceService;
|
||||
private WorkflowTask newTask;
|
||||
|
||||
public void testGetTypedItem() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(null);
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
processor.getTypedItem(new Item("task", "bad id"));
|
||||
fail("Should have thrown an Exception here!");
|
||||
}
|
||||
catch (WorkflowException e)
|
||||
{
|
||||
// Do nothing!
|
||||
}
|
||||
|
||||
Item item = new Item("task", TASK_ID);
|
||||
WorkflowTask result = processor.getTypedItem(item);
|
||||
assertNotNull(result);
|
||||
assertEquals(TASK_ID, result.id);
|
||||
}
|
||||
|
||||
public void testGenerateSetsItemAndUrl() throws Exception
|
||||
{
|
||||
Item item = new Item("task", TASK_ID);
|
||||
Form form = processor.generate(item, null, null, null);
|
||||
Item formItem = form.getItem();
|
||||
assertEquals(item.getId(), formItem.getId());
|
||||
assertEquals(item.getKind(), formItem.getKind());
|
||||
String expType = NamespaceService.BPM_MODEL_PREFIX + ":" + TASK_DEF_NAME;
|
||||
assertEquals(expType, formItem.getType());
|
||||
assertEquals("/api/task-instances/" + TASK_ID, formItem.getUrl());
|
||||
}
|
||||
|
||||
public void testGenerateSingleProperty()
|
||||
{
|
||||
// Check Status field is added to Form.
|
||||
String fieldName = STATUS_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
|
||||
// Check Status field is added to Form, when explicitly typed as a
|
||||
// property.
|
||||
String fullPropertyName = "prop:" + fieldName;
|
||||
fields = Arrays.asList(fullPropertyName);
|
||||
form = processForm(fields);
|
||||
checkSingleProperty(form, fieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
}
|
||||
|
||||
public void testGenerateSingleAssociation()
|
||||
{
|
||||
// Check Assignee field is added to Form.
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fieldName);
|
||||
Form form = processForm(fields);
|
||||
Serializable fieldData = (Serializable) Arrays.asList(FAKE_NODE.toString());
|
||||
// checkSingleAssociation(form, fieldName, fieldData);
|
||||
|
||||
// Check Assignee field is added to Form, when explicitly typed as an
|
||||
// association.
|
||||
String fullAssociationName = "assoc:" + fieldName;
|
||||
fields = Arrays.asList(fullAssociationName);
|
||||
form = processForm(fields);
|
||||
// checkSingleAssociation(form, fieldName, fieldData);
|
||||
}
|
||||
|
||||
public void testIgnoresUnknownFields() throws Exception
|
||||
{
|
||||
String fakeFieldName = NamespaceService.BPM_MODEL_PREFIX + ":" + "Fake Field";
|
||||
String statusFieldName = STATUS_NAME.toPrefixString(namespaceService);
|
||||
List<String> fields = Arrays.asList(fakeFieldName, statusFieldName);
|
||||
Form form = processForm(fields);
|
||||
checkSingleProperty(form, statusFieldName, WorkflowTaskState.IN_PROGRESS);
|
||||
}
|
||||
|
||||
public void testGenerateDefaultForm() throws Exception
|
||||
{
|
||||
Form form = processForm(null);
|
||||
List<String> fieldDefs = form.getFieldDefinitionNames();
|
||||
assertEquals(6, fieldDefs.size());
|
||||
assertTrue(fieldDefs.contains(ASSIGNEE_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(ACTORS_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(DESC_NAME.toPrefixString(namespaceService)));
|
||||
assertTrue(fieldDefs.contains(STATUS_NAME.toPrefixString(namespaceService)));
|
||||
|
||||
Serializable fieldData = (Serializable) Arrays.asList(FAKE_NODE.toString());
|
||||
FormData formData = form.getFormData();
|
||||
assertEquals(4, formData.getNumberOfFields());
|
||||
// assertEquals(fieldData, formData.getFieldData("assoc_bpm_assignee").getValue());
|
||||
assertEquals(WorkflowTaskState.IN_PROGRESS, formData.getFieldData("prop_bpm_status").getValue());
|
||||
}
|
||||
|
||||
public void testPersistPropertyChanged() throws Exception
|
||||
{
|
||||
String fieldName = DESC_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, FormFieldConstants.PROP_DATA_PREFIX);
|
||||
String value = "New Description";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
Map<QName, Serializable> actualProperties = retrievePropertyies();
|
||||
assertEquals(1, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(DESC_NAME));
|
||||
}
|
||||
|
||||
public void testPersistPropertyWith_() throws Exception
|
||||
{
|
||||
String fieldName = PROP_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, FormFieldConstants.PROP_DATA_PREFIX);
|
||||
String value = "New _ Value";
|
||||
|
||||
processPersist(dataKey, value);
|
||||
|
||||
Map<QName, Serializable> actualProperties = retrievePropertyies();
|
||||
assertEquals(1, actualProperties.size());
|
||||
assertEquals(value, actualProperties.get(PROP_WITH_));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<QName, Serializable> retrievePropertyies()
|
||||
{
|
||||
ArgumentCaptor<Map> mapArg = ArgumentCaptor.forClass(Map.class);
|
||||
verify(workflowService).updateTask(eq(TASK_ID), mapArg.capture(), anyMap(), anyMap());
|
||||
return mapArg.getValue();
|
||||
}
|
||||
|
||||
public void testPersistAssociationAdded() throws Exception
|
||||
{
|
||||
String fieldName = ACTORS_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, FormFieldConstants.ASSOC_DATA_PREFIX);
|
||||
dataKey = dataKey + FormFieldConstants.ASSOC_DATA_ADDED_SUFFIX;
|
||||
String nodeRef1 = FAKE_NODE.toString() + "1";
|
||||
String nodeRef2 = FAKE_NODE.toString() + "2";
|
||||
String value = nodeRef1 + ", " + nodeRef2;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
Map<QName, List<NodeRef>> actualAddedAssocs = retrieveAssociations(true);
|
||||
assertEquals(1, actualAddedAssocs.size());
|
||||
List<NodeRef> nodeRefs = actualAddedAssocs.get(ACTORS_NAME);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef1)));
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef2)));
|
||||
}
|
||||
|
||||
public void testPersistAssociationsRemoved() throws Exception
|
||||
{
|
||||
String fieldName = ASSIGNEE_NAME.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, FormFieldConstants.ASSOC_DATA_PREFIX);
|
||||
dataKey = dataKey + FormFieldConstants.ASSOC_DATA_REMOVED_SUFFIX;
|
||||
String value = FAKE_NODE.toString();
|
||||
processPersist(dataKey, value);
|
||||
|
||||
Map<QName, List<NodeRef>> actualRemovedAssocs = retrieveAssociations(false);
|
||||
assertEquals(1, actualRemovedAssocs.size());
|
||||
List<NodeRef> nodeRefs = actualRemovedAssocs.get(ASSIGNEE_NAME);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(1, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(FAKE_NODE));
|
||||
}
|
||||
|
||||
public void testPersistAssociationAddedWith_() throws Exception
|
||||
{
|
||||
String fieldName = ASSOC_WITH_.toPrefixString(namespaceService);
|
||||
String dataKey = makeDataKeyName(fieldName, FormFieldConstants.ASSOC_DATA_PREFIX);
|
||||
dataKey = dataKey + FormFieldConstants.ASSOC_DATA_ADDED_SUFFIX;
|
||||
String nodeRef1 = FAKE_NODE.toString() + "1";
|
||||
String nodeRef2 = FAKE_NODE.toString() + "2";
|
||||
String value = nodeRef1 + ", " + nodeRef2;
|
||||
processPersist(dataKey, value);
|
||||
|
||||
Map<QName, List<NodeRef>> actualAddedAssocs = retrieveAssociations(true);
|
||||
assertEquals(1, actualAddedAssocs.size());
|
||||
List<NodeRef> nodeRefs = actualAddedAssocs.get(ASSOC_WITH_);
|
||||
assertNotNull(nodeRefs);
|
||||
assertEquals(2, nodeRefs.size());
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef1)));
|
||||
assertTrue(nodeRefs.contains(new NodeRef(nodeRef2)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<QName, List<NodeRef>> retrieveAssociations(boolean added)
|
||||
{
|
||||
ArgumentCaptor<Map> mapArg = ArgumentCaptor.forClass(Map.class);
|
||||
if (added)
|
||||
{
|
||||
verify(workflowService).updateTask(eq(TASK_ID), anyMap(), mapArg.capture(), anyMap());
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(workflowService).updateTask(eq(TASK_ID), anyMap(), anyMap(), mapArg.capture());
|
||||
}
|
||||
return mapArg.getValue();
|
||||
}
|
||||
|
||||
private void processPersist(String dataKey, String value)
|
||||
{
|
||||
FormData data = new FormData();
|
||||
data.addFieldData(dataKey, value);
|
||||
Item item = new Item("task", TASK_ID);
|
||||
WorkflowTask persistedItem = (WorkflowTask) processor.persist(item, data);
|
||||
assertEquals(newTask, persistedItem);
|
||||
}
|
||||
|
||||
private Form processForm(List<String> fields)
|
||||
{
|
||||
Item item = new Item("task", TASK_ID);
|
||||
Form form = processor.generate(item, fields, null, null);
|
||||
return form;
|
||||
}
|
||||
|
||||
private void checkSingleProperty(Form form, String fieldName, Serializable fieldData)
|
||||
{
|
||||
checkSingleField(form, fieldName, fieldData, "prop_");
|
||||
|
||||
}
|
||||
|
||||
private void checkSingleAssociation(Form form, String fieldName, Serializable fieldData)
|
||||
{
|
||||
checkSingleField(form, fieldName, fieldData, "assoc_");
|
||||
|
||||
}
|
||||
|
||||
private void checkSingleField(Form form, String fieldName, Serializable fieldData, String prefix)
|
||||
{
|
||||
List<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
assertEquals(1, fieldDefs.size());
|
||||
FieldDefinition fieldDef = fieldDefs.get(0);
|
||||
assertEquals(fieldName, fieldDef.getName());
|
||||
String dataKey = fieldDef.getDataKeyName();
|
||||
String expDataKey = makeDataKeyName(fieldName, prefix);
|
||||
assertEquals(expDataKey, dataKey);
|
||||
FieldData data = form.getFormData().getFieldData(dataKey);
|
||||
assertEquals(fieldData, data.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fieldName
|
||||
* @param prefix
|
||||
* @return
|
||||
*/
|
||||
private String makeDataKeyName(String fieldName, String prefix)
|
||||
{
|
||||
return prefix + fieldName.replace(":", "_");
|
||||
}
|
||||
|
||||
/*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception
|
||||
{
|
||||
super.setUp();
|
||||
task = makeTask();
|
||||
workflowService = makeWorkflowService();
|
||||
DictionaryService dictionaryService = makeDictionaryService();
|
||||
namespaceService = makeNamespaceService();
|
||||
MockFieldProcessorRegistry fieldProcessorRegistry = new MockFieldProcessorRegistry(namespaceService,
|
||||
dictionaryService);
|
||||
DefaultFieldProcessor defaultProcessor = makeDefaultFieldProcessor(dictionaryService);
|
||||
processor = makeTaskFormProcessor(dictionaryService, fieldProcessorRegistry, defaultProcessor);
|
||||
}
|
||||
|
||||
private TaskFormProcessor makeTaskFormProcessor(DictionaryService dictionaryService,
|
||||
MockFieldProcessorRegistry fieldProcessorRegistry, DefaultFieldProcessor defaultProcessor)
|
||||
{
|
||||
TaskFormProcessor processor1 = new TaskFormProcessor();
|
||||
processor1.setWorkflowService(workflowService);
|
||||
processor1.setNamespaceService(namespaceService);
|
||||
processor1.setDictionaryService(dictionaryService);
|
||||
processor1.setFieldProcessorRegistry(fieldProcessorRegistry);
|
||||
return processor1;
|
||||
}
|
||||
|
||||
private DefaultFieldProcessor makeDefaultFieldProcessor(DictionaryService dictionaryService) throws Exception
|
||||
{
|
||||
DefaultFieldProcessor defaultProcessor = new DefaultFieldProcessor();
|
||||
defaultProcessor.setDictionaryService(dictionaryService);
|
||||
defaultProcessor.setNamespaceService(namespaceService);
|
||||
defaultProcessor.afterPropertiesSet();
|
||||
return defaultProcessor;
|
||||
}
|
||||
|
||||
private WorkflowTask makeTask()
|
||||
{
|
||||
WorkflowTask result = new WorkflowTask();
|
||||
result.id = TASK_ID;
|
||||
result.state = WorkflowTaskState.IN_PROGRESS;
|
||||
result.definition = makeTaskDefinition();
|
||||
result.properties = makeTaskProperties();
|
||||
return result;
|
||||
}
|
||||
|
||||
private HashMap<QName, Serializable> makeTaskProperties()
|
||||
{
|
||||
HashMap<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
properties.put(STATUS_NAME, WorkflowTaskState.IN_PROGRESS);
|
||||
properties.put(ASSIGNEE_NAME, FAKE_NODE);
|
||||
return properties;
|
||||
}
|
||||
|
||||
private WorkflowTaskDefinition makeTaskDefinition()
|
||||
{
|
||||
WorkflowTaskDefinition definition = new WorkflowTaskDefinition();
|
||||
definition.id = "DefinitionId";
|
||||
definition.metadata = makeTypeDef();
|
||||
definition.node = mock(WorkflowNode.class);
|
||||
return definition;
|
||||
}
|
||||
|
||||
private TypeDefinition makeTypeDef()
|
||||
{
|
||||
TypeDefinition typeDef = mock(TypeDefinition.class);
|
||||
QName name = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, TASK_DEF_NAME);
|
||||
when(typeDef.getName()).thenReturn(name);
|
||||
|
||||
// Set up task property definitions
|
||||
Map<QName, PropertyDefinition> propertyDefs = makeTaskPropertyDefs();
|
||||
when(typeDef.getProperties()).thenReturn(propertyDefs);
|
||||
|
||||
// Set up task association definitions.
|
||||
Map<QName, AssociationDefinition> associationDefs = makeTaskAssociationDefs();
|
||||
when(typeDef.getAssociations()).thenReturn(associationDefs);
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
private Map<QName, PropertyDefinition> makeTaskPropertyDefs()
|
||||
{
|
||||
Map<QName, PropertyDefinition> properties = new HashMap<QName, PropertyDefinition>();
|
||||
QName textType = DataTypeDefinition.TEXT;
|
||||
|
||||
// Add a Description property
|
||||
PropertyDefinition descValue = MockClassAttributeDefinition.mockPropertyDefinition(DESC_NAME, textType);
|
||||
properties.put(DESC_NAME, descValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition titleValue = MockClassAttributeDefinition.mockPropertyDefinition(STATUS_NAME, textType);
|
||||
properties.put(STATUS_NAME, titleValue);
|
||||
|
||||
// Add a Status property
|
||||
PropertyDefinition with_ = MockClassAttributeDefinition.mockPropertyDefinition(PROP_WITH_, textType);
|
||||
properties.put(PROP_WITH_, with_);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Map<QName, AssociationDefinition> makeTaskAssociationDefs()
|
||||
{
|
||||
Map<QName, AssociationDefinition> associations = new HashMap<QName, AssociationDefinition>();
|
||||
QName actorName = QName.createQName(NamespaceService.BPM_MODEL_1_0_URI, "Actor");
|
||||
|
||||
// Add Assigneee association
|
||||
MockClassAttributeDefinition assigneeDef = MockClassAttributeDefinition.mockAssociationDefinition(
|
||||
ASSIGNEE_NAME, actorName);
|
||||
associations.put(ASSIGNEE_NAME, assigneeDef);
|
||||
|
||||
// Add Assigneee association
|
||||
MockClassAttributeDefinition actorsDef = MockClassAttributeDefinition.mockAssociationDefinition(ACTORS_NAME,
|
||||
actorName);
|
||||
associations.put(ACTORS_NAME, actorsDef);
|
||||
|
||||
// Add association with _
|
||||
MockClassAttributeDefinition with_ = MockClassAttributeDefinition.mockAssociationDefinition(ASSOC_WITH_,
|
||||
actorName);
|
||||
associations.put(ASSOC_WITH_, with_);
|
||||
|
||||
return associations;
|
||||
}
|
||||
|
||||
private NamespaceService makeNamespaceService()
|
||||
{
|
||||
NamespaceServiceMemoryImpl nsService = new NamespaceServiceMemoryImpl();
|
||||
nsService.registerNamespace(NamespaceService.BPM_MODEL_PREFIX, NamespaceService.BPM_MODEL_1_0_URI);
|
||||
return nsService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DictionaryService makeDictionaryService()
|
||||
{
|
||||
DictionaryService mock = mock(DictionaryService.class);
|
||||
when(mock.getAnonymousType((QName) any(), (Collection<QName>) any())).thenReturn(task.definition.metadata);
|
||||
return mock;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private WorkflowService makeWorkflowService()
|
||||
{
|
||||
WorkflowService service = mock(WorkflowService.class);
|
||||
when(service.getTaskById(anyString())).thenAnswer(new Answer<WorkflowTask>()
|
||||
{
|
||||
|
||||
public WorkflowTask answer(InvocationOnMock invocation) throws Throwable
|
||||
{
|
||||
String id = (String) invocation.getArguments()[0];
|
||||
if (TASK_ID.equals(id))
|
||||
return task;
|
||||
else
|
||||
throw new WorkflowException("Task Id not found!");
|
||||
}
|
||||
});
|
||||
this.newTask = new WorkflowTask();
|
||||
newTask.id = TASK_ID;
|
||||
when(service.updateTask(anyString(), anyMap(), anyMap(), anyMap())).thenReturn(newTask);
|
||||
return service;
|
||||
}
|
||||
}
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A utility class for updating workflow tasks. This is a stateful object that
|
||||
* accumulates a set of updates to a task and then commits all the updates when
|
||||
* the update() method is called.
|
||||
*
|
||||
* @author Nick Smith
|
||||
*/
|
||||
public class TaskUpdater
|
||||
{
|
||||
/** Logger */
|
||||
private static final Log LOGGER = LogFactory.getLog(TaskUpdater.class);
|
||||
|
||||
private final String taskId;
|
||||
private final WorkflowService workflowService;
|
||||
private Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
private Map<QName, List<NodeRef>> add = new HashMap<QName, List<NodeRef>>();
|
||||
private Map<QName, List<NodeRef>> remove = new HashMap<QName, List<NodeRef>>();
|
||||
|
||||
public TaskUpdater(String taskId, WorkflowService workflowService)
|
||||
{
|
||||
this.taskId = taskId;
|
||||
this.workflowService = workflowService;
|
||||
}
|
||||
|
||||
public WorkflowTask update()
|
||||
{
|
||||
WorkflowTask result = workflowService.updateTask(taskId, properties, add, remove);
|
||||
properties = new HashMap<QName, Serializable>();
|
||||
add = new HashMap<QName, List<NodeRef>>();
|
||||
remove = new HashMap<QName, List<NodeRef>>();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addProperty(QName name, Serializable value)
|
||||
{
|
||||
properties.put(name, value);
|
||||
}
|
||||
|
||||
public void addAssociation(QName name, List<NodeRef> value)
|
||||
{
|
||||
add.put(name, value);
|
||||
}
|
||||
|
||||
public void removeAssociation(QName name, List<NodeRef> value)
|
||||
{
|
||||
remove.put(name, value);
|
||||
}
|
||||
|
||||
public boolean changeAssociation(QName name, String nodeRefs, boolean isAdd)
|
||||
{
|
||||
List<NodeRef> value = getNodeRefs(nodeRefs);
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Map<QName, List<NodeRef>> map = getAssociationMap(isAdd);
|
||||
if (map != null)
|
||||
{
|
||||
map.put(name, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param suffix
|
||||
* @return
|
||||
*/
|
||||
private Map<QName, List<NodeRef>> getAssociationMap(boolean isAdd)
|
||||
{
|
||||
Map<QName, List<NodeRef>> map = null;
|
||||
if (isAdd)
|
||||
{
|
||||
map = add;
|
||||
}
|
||||
else
|
||||
{
|
||||
map = remove;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<NodeRef> getNodeRefs(Object value)
|
||||
{
|
||||
String[] nodeRefIds = ((String) value).split(",");
|
||||
List<NodeRef> nodeRefs = new ArrayList<NodeRef>(nodeRefIds.length);
|
||||
for (String nodeRefString : nodeRefIds)
|
||||
{
|
||||
String nodeRefId = nodeRefString.trim();
|
||||
if (NodeRef.isNodeRef(nodeRefId))
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(nodeRefId);
|
||||
nodeRefs.add(nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
logNodeRefError(nodeRefId);
|
||||
}
|
||||
}
|
||||
return nodeRefs;
|
||||
}
|
||||
|
||||
private void logNodeRefError(String nodeRefId)
|
||||
{
|
||||
if (LOGGER.isWarnEnabled())
|
||||
{
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Target Node: ").append(nodeRefId);
|
||||
msg.append(" is not a valid NodeRef and has been ignored.");
|
||||
LOGGER.warn(msg.toString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2009 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.forms.processor.workflow;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.forms.FormException;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
*/
|
||||
public class TypedPropertyValueGetter
|
||||
{
|
||||
public static final String ON = "on";
|
||||
|
||||
public Serializable getValue(Object value, PropertyDefinition propDef)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Serializable typedValue = null;
|
||||
// before persisting check data type of property
|
||||
if (propDef.isMultiValued())
|
||||
{
|
||||
typedValue = processMultiValuedType(value);
|
||||
}
|
||||
else if (isBooleanProperty(propDef))
|
||||
{
|
||||
typedValue = processBooleanValue(value);
|
||||
}
|
||||
else if (isLocaleProperty(propDef))
|
||||
{
|
||||
typedValue = processLocaleValue(value);
|
||||
}
|
||||
else if (value instanceof String)
|
||||
{
|
||||
String valStr = (String) value;
|
||||
|
||||
// make sure empty strings stay as empty strings, everything else
|
||||
// should be represented as null
|
||||
if(valStr.isEmpty() && !isTextProperty(propDef))
|
||||
{
|
||||
// Do nothing, leave typedValue as null.
|
||||
}
|
||||
else
|
||||
{
|
||||
typedValue = valStr;
|
||||
}
|
||||
}
|
||||
else if (value instanceof Serializable)
|
||||
{
|
||||
typedValue = (Serializable) value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormException("Property values must be of a Serializable type! Value type: " + value.getClass());
|
||||
}
|
||||
return typedValue;
|
||||
}
|
||||
|
||||
private boolean isTextProperty(PropertyDefinition propDef)
|
||||
{
|
||||
return propDef.getDataType().getName().equals(DataTypeDefinition.TEXT) ||
|
||||
propDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT);
|
||||
}
|
||||
|
||||
private Boolean processBooleanValue(Object value)
|
||||
{
|
||||
// check for browser representation of true, that being "on"
|
||||
if (value instanceof String && ON.equals(value))
|
||||
{
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Boolean.FALSE; // TODO Check this line is OK with Gav.
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBooleanProperty(PropertyDefinition propDef)
|
||||
{
|
||||
return propDef.getDataType().getName().equals(DataTypeDefinition.BOOLEAN);
|
||||
}
|
||||
|
||||
private Serializable processLocaleValue(Object value)
|
||||
{
|
||||
if (value instanceof String)
|
||||
{
|
||||
return I18NUtil.parseLocale((String) value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormException("Locale property values must be represented as a String! Value is of type: "
|
||||
+ value.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLocaleProperty(PropertyDefinition propDef)
|
||||
{
|
||||
return propDef.getDataType().getName().equals(DataTypeDefinition.LOCALE);
|
||||
}
|
||||
|
||||
private Serializable processMultiValuedType(Object value)
|
||||
{
|
||||
// depending on client the value could be a comma separated string,
|
||||
// a List object or a JSONArray object
|
||||
if (value instanceof String)
|
||||
{
|
||||
String stringValue = (String) value;
|
||||
return processMultiValueString(stringValue);
|
||||
}
|
||||
else if (value instanceof JSONArray)
|
||||
{
|
||||
// if value is a JSONArray convert to List of Object
|
||||
JSONArray jsonArr = (JSONArray) value;
|
||||
return processJSONArray(jsonArr);
|
||||
}
|
||||
else if (value instanceof List<?>)
|
||||
{
|
||||
// persist the list
|
||||
return (Serializable) value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FormException("The value is an unsupported multi-value type: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
private Serializable processJSONArray(JSONArray jsonArr)
|
||||
{
|
||||
int arrLength = jsonArr.length();
|
||||
ArrayList<Object> list = new ArrayList<Object>(arrLength);
|
||||
try
|
||||
{
|
||||
for (int x = 0; x < arrLength; x++)
|
||||
{
|
||||
list.add(jsonArr.get(x));
|
||||
}
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new FormException("Failed to convert JSONArray to List", je);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Serializable processMultiValueString(String stringValue)
|
||||
{
|
||||
if (stringValue.length() == 0)
|
||||
{
|
||||
// empty string for multi-valued properties
|
||||
// should be stored as null
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if value is a String convert to List of String persist the List
|
||||
String[] values = stringValue.split(",");
|
||||
List<String> valueList = Arrays.asList(values);
|
||||
return new ArrayList<String>(valueList);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user