mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
First cut of MOB-837 (type support in forms)
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14606 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -39,7 +39,6 @@ import org.alfresco.repo.forms.AssociationFieldDefinition.Direction;
|
||||
import org.alfresco.repo.forms.PropertyFieldDefinition.FieldConstraint;
|
||||
import org.alfresco.repo.jscript.ClasspathScriptLocation;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
@@ -108,6 +107,7 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
private static final String USER_ONE = "UserOne_FormServiceImplTest";
|
||||
private static final String NODE_FORM_ITEM_KIND = "node";
|
||||
private static final String TYPE_FORM_ITEM_KIND = "type";
|
||||
|
||||
/**
|
||||
* Called during the transaction setup
|
||||
@@ -804,6 +804,55 @@ public class FormServiceImplTest extends BaseAlfrescoSpringTest
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: enable this once the RM caveat stuff is fixed
|
||||
public void xtestGetAllCreateForm() throws Exception
|
||||
{
|
||||
// get a form for the cm:content type
|
||||
Form form = this.formService.getForm(new Item(TYPE_FORM_ITEM_KIND, "cm:content"));
|
||||
|
||||
// check a form got returned
|
||||
assertNotNull("Expecting form to be present", form);
|
||||
|
||||
// check item identifier matches
|
||||
assertEquals(TYPE_FORM_ITEM_KIND, form.getItem().getKind());
|
||||
assertEquals("cm:content", form.getItem().getId());
|
||||
|
||||
// check the type is correct
|
||||
assertEquals(ContentModel.TYPE_CONTENT.toPrefixString(this.namespaceService),
|
||||
form.getItem().getType());
|
||||
|
||||
// check there is no group info
|
||||
assertNull("Expecting the form groups to be null!", form.getFieldGroups());
|
||||
|
||||
// check the field definitions
|
||||
Collection<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
assertNotNull("Expecting to find fields", fieldDefs);
|
||||
assertEquals("Expecting to find 11 fields", 11, fieldDefs.size());
|
||||
|
||||
// create a Map of the field definitions
|
||||
// NOTE: we can safely do this as we know there are no duplicate field names and we're not
|
||||
// concerned with ordering!
|
||||
Map<String, FieldDefinition> fieldDefMap = new HashMap<String, FieldDefinition>(fieldDefs.size());
|
||||
for (FieldDefinition fieldDef : fieldDefs)
|
||||
{
|
||||
fieldDefMap.put(fieldDef.getName(), fieldDef);
|
||||
}
|
||||
|
||||
// find the fields
|
||||
PropertyFieldDefinition nameField = (PropertyFieldDefinition)fieldDefMap.get("cm:name");
|
||||
PropertyFieldDefinition createdField = (PropertyFieldDefinition)fieldDefMap.get("cm:created");
|
||||
PropertyFieldDefinition creatorField = (PropertyFieldDefinition)fieldDefMap.get("cm:creator");
|
||||
PropertyFieldDefinition modifiedField = (PropertyFieldDefinition)fieldDefMap.get("cm:modified");
|
||||
PropertyFieldDefinition modifierField = (PropertyFieldDefinition)fieldDefMap.get("cm:modifier");
|
||||
|
||||
// check fields are present
|
||||
assertNotNull("Expecting to find the cm:name field", nameField);
|
||||
assertNotNull("Expecting to find the cm:created field", createdField);
|
||||
assertNotNull("Expecting to find the cm:creator field", creatorField);
|
||||
assertNotNull("Expecting to find the cm:modified field", modifiedField);
|
||||
assertNotNull("Expecting to find the cm:modifier field", modifierField);
|
||||
}
|
||||
|
||||
public void testNoForm() throws Exception
|
||||
{
|
||||
// test that a form can not be retrieved for a non-existent item
|
||||
|
@@ -26,6 +26,7 @@ package org.alfresco.repo.forms.processor.node;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -260,7 +261,7 @@ public class NodeFormProcessor extends FilteredFormProcessor
|
||||
|
||||
if (fields != null && fields.size() > 0)
|
||||
{
|
||||
generateSelectedFields(nodeRef, fields, forcedFields, form);
|
||||
generateSelectedFields(nodeRef, null, fields, forcedFields, form);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -273,28 +274,52 @@ public class NodeFormProcessor extends FilteredFormProcessor
|
||||
|
||||
/**
|
||||
* Sets up the field definitions for all the requested fields.
|
||||
* If any of the requested fields are not present on the node and they
|
||||
* appear in the forcedFields list an attempt to find a model
|
||||
* <p>
|
||||
* A NodeRef or TypeDefinition can be provided, however, if a NodeRef
|
||||
* is provided all type information will be derived from the NodeRef
|
||||
* and the TypeDefinition will be ignored.
|
||||
* </p><p>
|
||||
* If any of the requested fields are not present on the type and
|
||||
* they appear in the forcedFields list an attempt to find a model
|
||||
* definition for those fields is made so they can be included.
|
||||
* </p>
|
||||
*
|
||||
* @param nodeRef The NodeRef of the node being setup
|
||||
* @param nodeRef The NodeRef of the item being generated
|
||||
* @param typeDef The TypeDefiniton of the item being generated
|
||||
* @param fields Restricted list of fields to include
|
||||
* @param forcedFields List of field names that should be included
|
||||
* even if the field is not currently present
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateSelectedFields(NodeRef nodeRef, List<String> fields, List<String> forcedFields, Form form)
|
||||
protected void generateSelectedFields(NodeRef nodeRef, TypeDefinition typeDef,
|
||||
List<String> fields, List<String> forcedFields, Form form)
|
||||
{
|
||||
// ensure a NodeRef or TypeDefinition is provided
|
||||
if (nodeRef == null && typeDef == null)
|
||||
{
|
||||
throw new IllegalArgumentException("A NodeRef or TypeDefinition must be provided");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Generating selected fields: " + fields + " and forcing: " + forcedFields);
|
||||
|
||||
// get data dictionary definition for node
|
||||
QName type = this.nodeService.getType(nodeRef);
|
||||
TypeDefinition typeDef = this.dictionaryService.getAnonymousType(type,
|
||||
this.nodeService.getAspects(nodeRef));
|
||||
// get data dictionary definition for node if it is provided
|
||||
QName type = null;
|
||||
Map<QName, Serializable> propValues = Collections.emptyMap();
|
||||
|
||||
if (nodeRef != null)
|
||||
{
|
||||
type = this.nodeService.getType(nodeRef);
|
||||
typeDef = this.dictionaryService.getAnonymousType(type, this.nodeService.getAspects(nodeRef));
|
||||
propValues = this.nodeService.getProperties(nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = typeDef.getName();
|
||||
}
|
||||
|
||||
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
|
||||
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
|
||||
Map<QName, Serializable> propValues = this.nodeService.getProperties(nodeRef);
|
||||
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
|
||||
|
||||
for (String fieldName : fields)
|
||||
{
|
||||
@@ -365,7 +390,8 @@ public class NodeFormProcessor extends FilteredFormProcessor
|
||||
{
|
||||
// generate the association field
|
||||
generateAssociationField(assocDef,
|
||||
retrieveAssociationValues(nodeRef, assocDef), form);
|
||||
(nodeRef != null) ? retrieveAssociationValues(nodeRef, assocDef) : null,
|
||||
form);
|
||||
|
||||
foundField = true;
|
||||
}
|
||||
@@ -382,7 +408,8 @@ public class NodeFormProcessor extends FilteredFormProcessor
|
||||
else if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Ignoring field \"" + fieldName +
|
||||
"\" as it is not defined for the current node and it does not appear in the 'force' list");
|
||||
"\" as it is not defined for the current " + ((nodeRef != null) ? "node" : "type") +
|
||||
" and it does not appear in the 'force' list");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,7 +420,7 @@ public class NodeFormProcessor extends FilteredFormProcessor
|
||||
TRANSIENT_SIZE.equals(fieldName))
|
||||
{
|
||||
// if the node type is content or sublcass thereof generate appropriate field
|
||||
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
|
||||
if (nodeRef != null && this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
ContentData content = (ContentData)this.nodeService.getProperty(nodeRef, ContentModel.PROP_CONTENT);
|
||||
if (content != null)
|
||||
|
@@ -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.node;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.forms.Form;
|
||||
import org.alfresco.repo.forms.FormData;
|
||||
import org.alfresco.repo.forms.FormNotFoundException;
|
||||
import org.alfresco.repo.forms.Item;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.namespace.InvalidQNameException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* FormProcessor implementation that can generate and persist Form objects
|
||||
* for types in the Alfresco content model.
|
||||
*
|
||||
* @author Gavin Cornwell
|
||||
*/
|
||||
public class TypeFormProcessor extends NodeFormProcessor
|
||||
{
|
||||
/** Logger */
|
||||
private static Log logger = LogFactory.getLog(TypeFormProcessor.class);
|
||||
|
||||
@Override
|
||||
protected Object getTypedItem(Item item)
|
||||
{
|
||||
TypeDefinition typeDef = null;
|
||||
|
||||
try
|
||||
{
|
||||
// convert the prefix type into full QName representation
|
||||
// TODO: Also look for and deal with full QName as itemId
|
||||
QName type = QName.createQName(item.getId(), this.namespaceService);
|
||||
|
||||
// retrieve the type from the dictionary
|
||||
typeDef = this.dictionaryService.getType(type);
|
||||
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new FormNotFoundException(item,
|
||||
new IllegalArgumentException("Type does not exist: " + item.getId()));
|
||||
}
|
||||
}
|
||||
catch (InvalidQNameException iqne)
|
||||
{
|
||||
throw new FormNotFoundException(item, iqne);
|
||||
}
|
||||
|
||||
// return the type definition object for the requested type
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalGenerate(Object item, List<String> fields, List<String> forcedFields, Form form)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Generating form for item: " + item);
|
||||
|
||||
// cast to the expected NodeRef representation
|
||||
TypeDefinition typeDef = (TypeDefinition)item;
|
||||
|
||||
// generate the form for the node
|
||||
generateType(typeDef, fields, forcedFields, form);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Generating form: " + form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the Form object for the given NodeRef
|
||||
*
|
||||
* @param nodeRef The NodeRef to generate a Form for
|
||||
* @param fields Restricted list of fields to include
|
||||
* @param forcedFields List of fields to forcibly include
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateType(TypeDefinition typeDef, List<String> fields, List<String> forcedFields, Form form)
|
||||
{
|
||||
// set the type and URL of the item
|
||||
form.getItem().setType(typeDef.getName().toPrefixString(this.namespaceService));
|
||||
form.getItem().setUrl("/api/classes/" + typeDef.getName().toPrefixString(this.namespaceService).replace(":", "_"));
|
||||
|
||||
if (fields != null && fields.size() > 0)
|
||||
{
|
||||
generateSelectedFields(null, typeDef, fields, forcedFields, form);
|
||||
}
|
||||
else
|
||||
{
|
||||
// setup field definitions and data
|
||||
generateAllPropertyFields(typeDef, form);
|
||||
generateAllAssociationFields(typeDef, form);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the field definitions for all the type's properties.
|
||||
*
|
||||
* @param typeDef The type being setup
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateAllPropertyFields(TypeDefinition typeDef, Form form)
|
||||
{
|
||||
// iterate round the property defintions and setup field definition
|
||||
Map<QName, PropertyDefinition> propDefs = typeDef.getProperties();
|
||||
for (PropertyDefinition propDef : propDefs.values())
|
||||
{
|
||||
generatePropertyField(propDef, null, form);
|
||||
}
|
||||
|
||||
// get all default aspects for the type and iterate round their
|
||||
// property definitions too
|
||||
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
|
||||
for (AspectDefinition aspect : aspects)
|
||||
{
|
||||
propDefs = aspect.getProperties();
|
||||
for (PropertyDefinition propDef : propDefs.values())
|
||||
{
|
||||
generatePropertyField(propDef, null, form);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the field definitions for all the type's associations.
|
||||
*
|
||||
* @param typeDef The type being setup
|
||||
* @param form The Form instance to populate
|
||||
*/
|
||||
protected void generateAllAssociationFields(TypeDefinition typeDef, Form form)
|
||||
{
|
||||
// iterate round the association defintions and setup field definition
|
||||
Map<QName, AssociationDefinition> assocDefs = typeDef.getAssociations();
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
this.generateAssociationField(assocDef, null, form);
|
||||
}
|
||||
|
||||
// get all default aspects for the type and iterate round their
|
||||
// association definitions too
|
||||
List<AspectDefinition> aspects = typeDef.getDefaultAspects(true);
|
||||
for (AspectDefinition aspect : aspects)
|
||||
{
|
||||
assocDefs = aspect.getAssociations();
|
||||
for (AssociationDefinition assocDef : assocDefs.values())
|
||||
{
|
||||
this.generateAssociationField(assocDef, null, form);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object internalPersist(Object item, FormData data)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Persisting form for: " + item);
|
||||
|
||||
// cast to the expected NodeRef representation
|
||||
TypeDefinition typeDef = (TypeDefinition)item;
|
||||
|
||||
if (logger.isWarnEnabled())
|
||||
logger.warn("Persisting of 'type' form items has not been implemented yet!");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
@@ -51,8 +51,13 @@ public class ScriptForm implements Serializable
|
||||
this.form = formObject;
|
||||
|
||||
fieldDefinitionData = new HashMap<String, FieldDefinition>();
|
||||
for (FieldDefinition fd : form.getFieldDefinitions()) {
|
||||
fieldDefinitionData.put(fd.getName(), fd);
|
||||
List<FieldDefinition> fieldDefs = form.getFieldDefinitions();
|
||||
if (fieldDefs != null)
|
||||
{
|
||||
for (FieldDefinition fd : fieldDefs)
|
||||
{
|
||||
fieldDefinitionData.put(fd.getName(), fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,10 +51,13 @@ public class ScriptFormData implements Serializable
|
||||
public ScriptableHashMap<String, ScriptFieldData> getData()
|
||||
{
|
||||
ScriptableHashMap<String, ScriptFieldData> result = new ScriptableHashMap<String, ScriptFieldData>();
|
||||
for (String k : formData.getData().keySet())
|
||||
if (this.formData != null)
|
||||
{
|
||||
ScriptFieldData wrappedFieldData = new ScriptFieldData(formData.getData().get(k));
|
||||
result.put(k, wrappedFieldData);
|
||||
for (String k : formData.getData().keySet())
|
||||
{
|
||||
ScriptFieldData wrappedFieldData = new ScriptFieldData(formData.getData().get(k));
|
||||
result.put(k, wrappedFieldData);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user