First phase of the dialog & wizard framework (config implementation)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2552 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gavin Cornwell
2006-03-16 15:07:25 +00:00
parent 092a41063f
commit dd70d72198
9 changed files with 1224 additions and 59 deletions

View File

@@ -0,0 +1,202 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.config;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.element.ConfigElementAdapter;
import org.alfresco.util.ParameterCheck;
/**
* Custom config element that represents the config data for a property sheet
*
* @author gavinc
*/
public class DialogsConfigElement extends ConfigElementAdapter
{
public static final String CONFIG_ELEMENT_ID = "dialogs";
private Map<String, DialogConfig> dialogs = new LinkedHashMap<String, DialogConfig>(8, 10f);
/**
* Default constructor
*/
public DialogsConfigElement()
{
super(CONFIG_ELEMENT_ID);
}
/**
* Constructor
*
* @param name Name of the element this config element represents
*/
public DialogsConfigElement(String name)
{
super(name);
}
/**
* @see org.alfresco.config.ConfigElement#getChildren()
*/
public List<ConfigElement> getChildren()
{
throw new ConfigException("Reading the dialogs config via the generic interfaces is not supported");
}
/**
* @see org.alfresco.config.ConfigElement#combine(org.alfresco.config.ConfigElement)
*/
public ConfigElement combine(ConfigElement configElement)
{
DialogsConfigElement combined = new DialogsConfigElement();
// add all the dialogs from this element
for (DialogConfig dialog : this.getDialogs().values())
{
combined.addDialog(dialog);
}
// add all the dialogs from the given element
for (DialogConfig dialog : ((DialogsConfigElement)configElement).getDialogs().values())
{
combined.addDialog(dialog);
}
return combined;
}
/**
* Adds a dialog
*
* @param dialogConfig A pre-configured dialog config object
*/
/*package*/ void addDialog(DialogConfig dialogConfig)
{
this.dialogs.put(dialogConfig.getName(), dialogConfig);
}
/**
* Returns the named dialog
*
* @param name The name of the dialog to retrieve
* @return The DialogConfig object for the requested dialog or null if it doesn't exist
*/
public DialogConfig getDialog(String name)
{
return this.dialogs.get(name);
}
/**
* @return Returns a map of the dialogs. A linked hash map is used internally to
* preserve ordering.
*/
public Map<String, DialogConfig> getDialogs()
{
return this.dialogs;
}
/**
* Inner class representing the configuration of a single dialog
*
* @author gavinc
*/
public static class DialogConfig
{
protected String name;
protected String page;
protected String managedBean;
protected String title;
protected String titleId;
protected String description;
protected String descriptionId;
public DialogConfig(String name, String page, String bean,
String title, String titleId,
String description, String descriptionId)
{
// check the mandatory parameters are present
ParameterCheck.mandatoryString("name", name);
ParameterCheck.mandatoryString("page", page);
ParameterCheck.mandatoryString("managedBean", bean);
this.name = name;
this.page = page;
this.managedBean = bean;
this.title = title;
this.titleId = titleId;
this.description = description;
this.descriptionId = descriptionId;
}
public String getDescription()
{
return this.description;
}
public String getDescriptionId()
{
return this.descriptionId;
}
public String getManagedBean()
{
return this.managedBean;
}
public String getName()
{
return this.name;
}
public String getPage()
{
return this.page;
}
public String getTitle()
{
return this.title;
}
public String getTitleId()
{
return this.titleId;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (name=").append(this.name);
buffer.append(" page=").append(this.page);
buffer.append(" managed-bean=").append(this.managedBean);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
buffer.append(" description=").append(this.description);
buffer.append(" descriptionId=").append(this.descriptionId).append(")");
return buffer.toString();
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.config;
import java.util.Iterator;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.xml.elementreader.ConfigElementReader;
import org.dom4j.Element;
/**
* Custom element reader to parse config for dialogs
*
* @author gavinc
*/
public class DialogsElementReader implements ConfigElementReader
{
public static final String ELEMENT_DIALOGS = "dialogs";
public static final String ELEMENT_DIALOG = "dialog";
public static final String ATTR_NAME = "name";
public static final String ATTR_PAGE = "page";
public static final String ATTR_MANAGED_BEAN = "managed-bean";
public static final String ATTR_TITLE = "title";
public static final String ATTR_TITLE_ID = "title-id";
public static final String ATTR_DESCRIPTION = "description";
public static final String ATTR_DESCRIPTION_ID = "description-id";
/**
* @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element)
*/
public ConfigElement parse(Element element)
{
DialogsConfigElement configElement = null;
if (element != null)
{
String elementName = element.getName();
if (elementName.equals(ELEMENT_DIALOGS) == false)
{
throw new ConfigException("DialogsElementReader can only parse " +
ELEMENT_DIALOGS + "elements, the element passed was '" +
elementName + "'");
}
configElement = new DialogsConfigElement();
// go through the items to show
Iterator<Element> items = element.elementIterator(ELEMENT_DIALOG);
while (items.hasNext())
{
Element item = items.next();
String name = item.attributeValue(ATTR_NAME);
String page = item.attributeValue(ATTR_PAGE);
String bean = item.attributeValue(ATTR_MANAGED_BEAN);
String title = item.attributeValue(ATTR_TITLE);
String titleId = item.attributeValue(ATTR_TITLE_ID);
String description = item.attributeValue(ATTR_DESCRIPTION);
String descriptionId = item.attributeValue(ATTR_DESCRIPTION_ID);
DialogsConfigElement.DialogConfig cfg = new DialogsConfigElement.DialogConfig(
name, page, bean, title, titleId, description, descriptionId);
configElement.addDialog(cfg);
}
}
return configElement;
}
}

View File

@@ -17,8 +17,7 @@
package org.alfresco.web.config; package org.alfresco.web.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -36,12 +35,18 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
// TODO: Currently this object just deals with properties and associations to show, // TODO: Currently this object just deals with properties and associations to show,
// in the future it will also deal with properties and associations to hide. // in the future it will also deal with properties and associations to hide.
private List<ItemConfig> items = new ArrayList<ItemConfig>(); public static final String CONFIG_ELEMENT_ID = "property-sheet";
private List<ItemConfig> editableItems = new ArrayList<ItemConfig>();
private Map<String, ItemConfig> itemsMap = new HashMap<String, ItemConfig>(); protected Map<String, ItemConfig> items = new LinkedHashMap<String, ItemConfig>(8, 10f);
private Map<String, ItemConfig> editableItemsMap = new HashMap<String, ItemConfig>(); protected Map<String, ItemConfig> editableItems = new LinkedHashMap<String, ItemConfig>(8, 10f);
private List<String> itemNames = new ArrayList<String>();
private List<String> editableItemNames = new ArrayList<String>();
//private List<ItemConfig> items = new ArrayList<ItemConfig>();
//private List<ItemConfig> editableItems = new ArrayList<ItemConfig>();
//private Map<String, ItemConfig> itemsMap = new HashMap<String, ItemConfig>();
//private Map<String, ItemConfig> editableItemsMap = new HashMap<String, ItemConfig>();
//private List<String> itemNames = new ArrayList<String>();
//private List<String> editableItemNames = new ArrayList<String>();
private boolean kidsPopulated = false; private boolean kidsPopulated = false;
/** /**
@@ -49,7 +54,7 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
*/ */
public PropertySheetConfigElement() public PropertySheetConfigElement()
{ {
super("property-sheet"); super(CONFIG_ELEMENT_ID);
} }
/** /**
@@ -76,10 +81,8 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
{ {
if (this.kidsPopulated == false) if (this.kidsPopulated == false)
{ {
Iterator<ItemConfig> items = this.items.iterator(); for (ItemConfig pc : this.items.values())
while (items.hasNext())
{ {
ItemConfig pc = items.next();
GenericConfigElement ce = null; GenericConfigElement ce = null;
if (pc instanceof PropertyConfig) if (pc instanceof PropertyConfig)
{ {
@@ -120,17 +123,15 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
PropertySheetConfigElement combined = new PropertySheetConfigElement(); PropertySheetConfigElement combined = new PropertySheetConfigElement();
// add all the existing properties // add all the existing properties
Iterator<ItemConfig> items = this.getItemsToShow().iterator(); for (ItemConfig item : this.getItemsToShow().values())
while (items.hasNext())
{ {
combined.addItem(items.next()); combined.addItem(item);
} }
// add all the properties from the given element // add all the properties from the given element
items = ((PropertySheetConfigElement)configElement).getItemsToShow().iterator(); for (ItemConfig item : ((PropertySheetConfigElement)configElement).getItemsToShow().values())
while (items.hasNext())
{ {
combined.addItem(items.next()); combined.addItem(item);
} }
return combined; return combined;
@@ -143,18 +144,19 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
*/ */
/*package*/ void addItem(ItemConfig itemConfig) /*package*/ void addItem(ItemConfig itemConfig)
{ {
if (this.itemsMap.containsKey(itemConfig.getName()) == false) this.items.put(itemConfig.getName(), itemConfig);
{
this.items.add(itemConfig);
this.itemsMap.put(itemConfig.getName(), itemConfig);
this.itemNames.add(itemConfig.getName());
// also add to the edit items collections if necessary // remove the item from the map if it is no longer editable
if (itemConfig.isShownInEditMode()) if (itemConfig.isShownInEditMode())
{ {
this.editableItems.add(itemConfig); this.editableItems.put(itemConfig.getName(), itemConfig);
this.editableItemsMap.put(itemConfig.getName(), itemConfig); }
this.editableItemNames.add(itemConfig.getName()); else
{
// if the item was added previously as editable it should be removed
if (editableItems.containsKey(itemConfig.getName()))
{
this.editableItems.remove(itemConfig.getName());
} }
} }
} }
@@ -216,23 +218,22 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
*/ */
public List<String> getItemNamesToShow() public List<String> getItemNamesToShow()
{ {
return this.itemNames; List<String> propNames = new ArrayList<String>(this.items.size());
for (String name : this.items.keySet())
{
propNames.add(name);
} }
/** return propNames;
* @return Returns the list of item config objects that represent those to display
*/
public List<ItemConfig> getItemsToShow()
{
return this.items;
} }
/** /**
* @return Returns a map of the item names to show * @return Returns a map of the item names to show
*/ */
public Map<String, ItemConfig> getItemsMapToShow() public Map<String, ItemConfig> getItemsToShow()
{ {
return this.itemsMap; return this.items;
} }
/** /**
@@ -240,23 +241,22 @@ public class PropertySheetConfigElement extends ConfigElementAdapter
*/ */
public List<String> getEditableItemNamesToShow() public List<String> getEditableItemNamesToShow()
{ {
return this.editableItemNames; List<String> propNames = new ArrayList<String>(this.editableItems.size());
for (String name : this.editableItems.keySet())
{
propNames.add(name);
} }
/** return propNames;
* @return Returns the list of item config objects that represent those to display
*/
public List<ItemConfig> getEditableItemsToShow()
{
return this.editableItems;
} }
/** /**
* @return Returns a map of the item names to show * @return Returns a map of the item names to show
*/ */
public Map<String, ItemConfig> getEditableItemsMapToShow() public Map<String, ItemConfig> getEditableItemsToShow()
{ {
return this.editableItemsMap; return this.editableItems;
} }
/** /**

View File

@@ -17,6 +17,7 @@
package org.alfresco.web.config; package org.alfresco.web.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -27,7 +28,12 @@ import org.alfresco.config.source.FileConfigSource;
import org.alfresco.config.xml.XMLConfigService; import org.alfresco.config.xml.XMLConfigService;
import org.alfresco.util.BaseTest; import org.alfresco.util.BaseTest;
import org.alfresco.web.config.AdvancedSearchConfigElement.CustomProperty; import org.alfresco.web.config.AdvancedSearchConfigElement.CustomProperty;
import org.alfresco.web.config.DialogsConfigElement.DialogConfig;
import org.alfresco.web.config.PropertySheetConfigElement.ItemConfig; import org.alfresco.web.config.PropertySheetConfigElement.ItemConfig;
import org.alfresco.web.config.WizardsConfigElement.ConditionalPageConfig;
import org.alfresco.web.config.WizardsConfigElement.PageConfig;
import org.alfresco.web.config.WizardsConfigElement.StepConfig;
import org.alfresco.web.config.WizardsConfigElement.WizardConfig;
/** /**
* JUnit tests to exercise the capabilities added to the web client config * JUnit tests to exercise the capabilities added to the web client config
@@ -79,7 +85,7 @@ public class WebClientConfigTest extends BaseTest
assertTrue("There should be 6 properties in the list", propNames.size() == 6); assertTrue("There should be 6 properties in the list", propNames.size() == 6);
// make sure the property sheet config has come back with the correct data // make sure the property sheet config has come back with the correct data
Map<String, ItemConfig> props = spacePropConfig.getItemsMapToShow(); Map<String, ItemConfig> props = spacePropConfig.getItemsToShow();
ItemConfig descProp = props.get("description"); ItemConfig descProp = props.get("description");
assertNotNull("description property config should not be null", descProp); assertNotNull("description property config should not be null", descProp);
assertEquals("display label for description should be 'Description'", descProp.getDisplayLabel(), assertEquals("display label for description should be 'Description'", descProp.getDisplayLabel(),
@@ -186,7 +192,7 @@ public class WebClientConfigTest extends BaseTest
assertEquals("third property name", "icon", itemNamesToEdit.get(2)); assertEquals("third property name", "icon", itemNamesToEdit.get(2));
// make sure the map has the correct number of items // make sure the map has the correct number of items
Map<String, ItemConfig> itemsToEditMap = propSheet.getEditableItemsMapToShow(); Map<String, ItemConfig> itemsToEditMap = propSheet.getEditableItemsToShow();
assertNotNull("itemsToEditMap should not be null", itemsToEditMap); assertNotNull("itemsToEditMap should not be null", itemsToEditMap);
assertEquals("Number of properties", 3, itemsToEditMap.size()); assertEquals("Number of properties", 3, itemsToEditMap.size());
@@ -200,11 +206,45 @@ public class WebClientConfigTest extends BaseTest
assertNull("size should be null", item); assertNull("size should be null", item);
// make sure the list has the correct numbe of items // make sure the list has the correct numbe of items
List<ItemConfig> itemsToEdit = propSheet.getEditableItemsToShow(); Collection<ItemConfig> itemsToEdit = propSheet.getEditableItemsToShow().values();
assertNotNull("itemsToEdit should not be null", itemsToEdit); assertNotNull("itemsToEdit should not be null", itemsToEdit);
assertEquals("Number of properties", 3, itemsToEdit.size()); assertEquals("Number of properties", 3, itemsToEdit.size());
} }
public void testPropertyOverride()
{
// setup the config service
List<String> configFiles = new ArrayList<String>(2);
configFiles.add(getResourcesDir() + "test-config.xml");
configFiles.add(getResourcesDir() + "test-config-override.xml");
XMLConfigService svc = new XMLConfigService(new FileConfigSource(configFiles));
svc.init();
// get the config for the size property in the space-aspect property sheet
PropertySheetConfigElement propSheet = ((PropertySheetConfigElement)svc.getConfig("space-aspect").
getConfigElement(PropertySheetConfigElement.CONFIG_ELEMENT_ID));
assertNotNull("propSheet should not be null", propSheet);
// make sure the list and map numbers are correct
assertEquals("prop names to show size", 6, propSheet.getItemNamesToShow().size());
assertEquals("props to show size", 6, propSheet.getItemsToShow().size());
assertEquals("edit prop names to show size", 5, propSheet.getEditableItemNamesToShow().size());
assertEquals("edit props to show size", 5, propSheet.getEditableItemsToShow().size());
PropertySheetConfigElement.PropertyConfig propConfig =
(PropertySheetConfigElement.PropertyConfig)propSheet.getItemsToShow().get("size");
assertNotNull("propConfig should not be null", propConfig);
// make sure config has been overridden
assertTrue("size should be shown in edit mode", propConfig.isShownInEditMode());
assertTrue("size property should be read only", propConfig.isReadOnly());
assertNotNull("size property should be in edit map", propSheet.getEditableItemsToShow().get("size"));
// get the icon
propConfig = (PropertySheetConfigElement.PropertyConfig)propSheet.getItemsToShow().get("icon");
assertNotNull("propConfig should not be null", propConfig);
}
/** /**
* Tests the custom client configuration objects * Tests the custom client configuration objects
*/ */
@@ -542,4 +582,188 @@ public class WebClientConfigTest extends BaseTest
// expected // expected
} }
} }
public void testDialogs()
{
// setup the config service
String configFiles = getResourcesDir() + "test-config-dialogs-wizards.xml";
XMLConfigService svc = new XMLConfigService(new FileConfigSource(configFiles));
svc.init();
// get Dialogs config section
Config dialogsConfig = svc.getConfig("Dialogs");
assertNotNull("dialogsConfig should not be null", dialogsConfig);
// make sure the dialog-container is correct
assertEquals("dialog container", "/jsp/dialog/container.jsp",
dialogsConfig.getConfigElement("dialog-container").getValue());
// make sure a non existent dialog returns null
assertNull("non existent dialog test should return null",
dialogsConfig.getConfigElement("Non Existent Dialog"));
// get the dialogs element
DialogsConfigElement dialogsElement = (DialogsConfigElement)dialogsConfig.
getConfigElement(DialogsConfigElement.CONFIG_ELEMENT_ID);
assertNotNull("dialogsElement should not be null", dialogsElement);
// make sure there are 2 items in the list and map
assertEquals("map size", 2, dialogsElement.getDialogs().size());
// get the 'createSpace' dialog
DialogConfig dialog = dialogsElement.getDialog("createSpace");
assertNotNull("createSpace dialog config should not be null", dialog);
// make sure the info on the dialog is correct
assertEquals("name", "createSpace", dialog.getName());
assertEquals("page", "/jsp/dialog/create-space.jsp", dialog.getPage());
assertEquals("managed-bean", "NewSpaceDialog", dialog.getManagedBean());
assertEquals("title-id", "create_space_title", dialog.getTitleId());
assertEquals("description-id", "create_space_description", dialog.getDescriptionId());
assertNull("title should be null", dialog.getTitle());
assertNull("description should be null", dialog.getDescription());
// get the 'spaceDetails' dialog
dialog = dialogsElement.getDialog("spaceDetails");
assertNotNull("spaceDetails dialog config should not be null", dialog);
// make sure the info on the dialog is correct
assertEquals("name", "spaceDetails", dialog.getName());
assertEquals("page", "/jsp/dialog/space-details.jsp", dialog.getPage());
assertEquals("managed-bean", "SpaceDetailsDialog", dialog.getManagedBean());
assertEquals("title", "Space Details Dialog", dialog.getTitle());
assertEquals("description", "Space Details Dialog Decsription", dialog.getDescription());
assertNull("title-id should be null", dialog.getTitleId());
assertNull("description-id should be null", dialog.getDescriptionId());
}
public void testDialogOverride()
{
// setup the config service
List<String> configFiles = new ArrayList<String>(2);
configFiles.add(getResourcesDir() + "test-config-dialogs-wizards.xml");
configFiles.add(getResourcesDir() + "test-config-override.xml");
XMLConfigService svc = new XMLConfigService(new FileConfigSource(configFiles));
svc.init();
// get the 'dialogs' element
DialogsConfigElement dialogsElement = ((DialogsConfigElement)svc.getConfig("Dialogs").
getConfigElement(DialogsConfigElement.CONFIG_ELEMENT_ID));
// make sure there are 2 items in the list and map
assertEquals("map size", 2, dialogsElement.getDialogs().size());
// get the 'createSpace' dialog
DialogConfig dialog = dialogsElement.getDialog("createSpace");
assertNotNull("createSpace dialog should not be null", dialog);
// make sure the page and managed bean attributes have been overridden
assertEquals("page", "/custom/my-create-space.jsp", dialog.getPage());
assertEquals("managed-bean", "MyNewSpaceDialog", dialog.getManagedBean());
assertEquals("title-id", "create_space_title", dialog.getTitleId());
assertEquals("description-id", "create_space_description", dialog.getDescriptionId());
}
public void testWizards()
{
// setup the config service
String configFiles = getResourcesDir() + "test-config-dialogs-wizards.xml";
XMLConfigService svc = new XMLConfigService(new FileConfigSource(configFiles));
svc.init();
// get Dialogs config section
Config wizardsConfig = svc.getConfig("Wizards");
assertNotNull("wizardsConfig should not be null", wizardsConfig);
// make sure the wizard-container is correct
assertEquals("wizard container", "/jsp/wizard/container.jsp",
wizardsConfig.getConfigElement("wizard-container").getValue());
// make sure a non existent wizard returns null
assertNull("non existent wizard should not be null",
wizardsConfig.getConfigElement("Non Existent Wizard"));
// get the wizards element
WizardsConfigElement wizardsElement = (WizardsConfigElement)wizardsConfig.
getConfigElement(WizardsConfigElement.CONFIG_ELEMENT_ID);
assertNotNull("wizardsElement should not be null", wizardsElement);
// make sure there are 2 items in the map
assertEquals("map size", 2, wizardsElement.getWizards().size());
// get the 'exampleWizard' wizard
WizardConfig wizard = wizardsElement.getWizard("exampleWizard");
assertNotNull("exampleWizard wizard should not be null", wizard);
// make sure data is correct
assertEquals("name", "exampleWizard", wizard.getName());
assertEquals("exampleWizard steps", 2, wizard.getNumberSteps());
assertEquals("managed-bean", "ExampleWizard", wizard.getManagedBean());
assertEquals("title", "Example Wizard Title", wizard.getTitle());
assertEquals("description", "Example Wizard Description", wizard.getDescription());
assertNull("title-id should be null", wizard.getTitleId());
assertNull("description-id should be null", wizard.getDescriptionId());
// get the 'createSpace' wizard and ensure all the data is correct
wizard = wizardsElement.getWizard("createSpace");
assertEquals("name", "createSpace", wizard.getName());
assertEquals("createSpace steps", 3, wizard.getNumberSteps());
assertEquals("managed-bean", "AdvancedSpaceWizard", wizard.getManagedBean());
assertEquals("title-id", "advanced_space_details_title", wizard.getTitleId());
assertEquals("description-id", "advanced_space_details_description", wizard.getDescriptionId());
assertNull("title should be null", wizard.getTitle());
assertNull("description should be null", wizard.getDescription());
List<StepConfig> steps = wizard.getSteps();
assertNotNull("steps should not be null", steps);
// retrieve step1 information and check it is correct
StepConfig step1 = steps.get(0);
assertEquals("step 1 name", "details", step1.getName());
assertFalse("step 1 should not have conditional pages", step1.hasConditionalPages());
PageConfig step1Page = step1.getDefaultPage();
assertNotNull("step1Page should not be null", step1Page);
assertEquals("step 1 page", "/jsp/wizard/new-space/create-from.jsp", step1Page.getPath());
assertEquals("step 1 title-id", "create_space_details_title", step1Page.getTitleId());
assertEquals("step 1 description-id", "create_space_details_desc", step1Page.getDescriptionId());
assertEquals("step 1 instruction-id", "create_space_details_instruction", step1Page.getInstructionId());
assertNull("step 1 title should be null", step1Page.getTitle());
assertNull("step 1 description should be null", step1Page.getDescription());
// check the conditional step2 data
StepConfig step2 = steps.get(1);
assertEquals("step 2 name", "properties", step2.getName());
assertTrue("step 2 should have conditional pages", step2.hasConditionalPages());
PageConfig step2DefaultPage = step2.getDefaultPage();
assertNotNull("step 2 default page should not be null", step2DefaultPage);
assertEquals("step 2 default page", "/jsp/wizard/new-space/from-scratch.jsp", step2DefaultPage.getPath());
assertEquals("step 2 default title-id", "create_space_scratch_title", step2DefaultPage.getTitleId());
assertEquals("step 2 default description-id", "create_space_scratch_desc", step2DefaultPage.getDescriptionId());
assertEquals("step 2 default instruction-id", "create_space_scratch_instruction", step2DefaultPage.getInstructionId());
assertNull("step 2 default title should be null", step2DefaultPage.getTitle());
assertNull("step 2 default description should be null", step2DefaultPage.getDescription());
List<ConditionalPageConfig> conditionalPages = step2.getConditionalPages();
assertEquals("number of conditional pages for step 2", 1, conditionalPages.size());
ConditionalPageConfig step2CondPage = conditionalPages.get(0);
assertNotNull("step 2 cond page should not be null", step2CondPage);
assertEquals("step 2 conditon", "#{AdvancedSpaceWizard.createFrom == 'template'}", step2CondPage.getCondition());
assertEquals("step 2 cond page", "/jsp/wizard/new-space/from-template.jsp", step2CondPage.getPath());
assertEquals("step 2 cond title-id", "create_space_template_title", step2CondPage.getTitleId());
assertEquals("step 2 cond description-id", "create_space_template_desc", step2CondPage.getDescriptionId());
assertEquals("step 2 cond instruction-id", "create_space_template_instruction", step2CondPage.getInstructionId());
assertNull("step 2 cond title should be null", step2CondPage.getTitle());
assertNull("step 2 cond description should be null", step2CondPage.getDescription());
// check step 3 data
StepConfig step3 = steps.get(2);
assertEquals("step 3 name", "summary", step3.getName());
assertFalse("step 3 should not have conditional pages", step3.hasConditionalPages());
PageConfig step3Page = step3.getDefaultPage();
assertNotNull("step3Page should not be null", step3Page);
assertEquals("step 3 page", "/jsp/wizard/new-space/summary.jsp", step3Page.getPath());
assertEquals("step 3 title-id", "create_space_summary_title", step3Page.getTitleId());
assertEquals("step 3 description-id", "create_space_summary_desc", step3Page.getDescriptionId());
assertEquals("step 3 instruction-id", "create_space_summary_instruction", step3Page.getInstructionId());
assertNull("step 3 title should be null", step3Page.getTitle());
assertNull("step 3 description should be null", step3Page.getDescription());
}
} }

View File

@@ -0,0 +1,399 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.config;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.element.ConfigElementAdapter;
import org.alfresco.util.ParameterCheck;
/**
* Custom config element that represents the config data for a property sheet
*
* @author gavinc
*/
public class WizardsConfigElement extends ConfigElementAdapter
{
public static final String CONFIG_ELEMENT_ID = "wizards";
private Map<String, WizardConfig> wizards = new LinkedHashMap<String, WizardConfig>(8, 10f);
/**
* Default constructor
*/
public WizardsConfigElement()
{
super(CONFIG_ELEMENT_ID);
}
/**
* Constructor
*
* @param name Name of the element this config element represents
*/
public WizardsConfigElement(String name)
{
super(name);
}
/**
* @see org.alfresco.config.ConfigElement#getChildren()
*/
public List<ConfigElement> getChildren()
{
throw new ConfigException("Reading the wizards config via the generic interfaces is not supported");
}
/**
* @see org.alfresco.config.ConfigElement#combine(org.alfresco.config.ConfigElement)
*/
public ConfigElement combine(ConfigElement configElement)
{
WizardsConfigElement combined = new WizardsConfigElement();
// add all the wizards from this element
for (WizardConfig wizard : this.getWizards().values())
{
combined.addWizard(wizard);
}
// add all the wizards from the given element
for (WizardConfig wizard : ((WizardsConfigElement)configElement).getWizards().values())
{
combined.addWizard(wizard);
}
return combined;
}
/**
* Adds a wizard
*
* @param wizardConfig A pre-configured wizard config object
*/
/*package*/ void addWizard(WizardConfig wizardConfig)
{
this.wizards.put(wizardConfig.getName(), wizardConfig);
}
/**
* Returns the named wizard
*
* @param name The name of the wizard to retrieve
* @return The WizardConfig object for the requested wizard or null if it doesn't exist
*/
public WizardConfig getWizard(String name)
{
return this.wizards.get(name);
}
/**
* @return Returns a map of the wizards
*/
public Map<String, WizardConfig> getWizards()
{
return this.wizards;
}
public abstract static class AbstractConfig
{
protected String title;
protected String titleId;
protected String description;
protected String descriptionId;
public AbstractConfig(String title, String titleId,
String description, String descriptionId)
{
this.title = title;
this.titleId = titleId;
this.description = description;
this.descriptionId = descriptionId;
}
public String getDescription()
{
return this.description;
}
public String getDescriptionId()
{
return this.descriptionId;
}
public String getTitle()
{
return this.title;
}
public String getTitleId()
{
return this.titleId;
}
}
/**
* Represents the configuration of a single wizard i.e. the &lt;wizard&gt; element
*/
public static class WizardConfig extends AbstractConfig
{
protected String name;
protected String managedBean;
protected List<StepConfig> steps = new ArrayList<StepConfig>(4);
public WizardConfig(String name, String bean,
String title, String titleId,
String description, String descriptionId)
{
super(title, titleId, description, descriptionId);
// check we have a name
ParameterCheck.mandatoryString("name", name);
this.name = name;
this.managedBean = bean;
}
public String getName()
{
return this.name;
}
public String getManagedBean()
{
return this.managedBean;
}
public void addStep(StepConfig step)
{
this.steps.add(step);
}
public int getNumberSteps()
{
return this.steps.size();
}
public List<StepConfig> getSteps()
{
return this.steps;
}
public StepConfig getStepByName(String name)
{
StepConfig step = null;
for (StepConfig currentStep : this.steps)
{
if (currentStep.getName().equals(name))
{
step = currentStep;
break;
}
}
return step;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (name=").append(this.name);
buffer.append(" managed-bean=").append(this.managedBean);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
buffer.append(" description=").append(this.description);
buffer.append(" descriptionId=").append(this.descriptionId).append(")");
return buffer.toString();
}
}
/**
* Represents the configuration of a page in a wizard i.e. the &lt;page&gt; element
*/
public static class PageConfig extends AbstractConfig
{
protected String path;
protected String instruction;
protected String instructionId;
public PageConfig(String path,
String title, String titleId,
String description, String descriptionId,
String instruction, String instructionId)
{
super(title, titleId, description, descriptionId);
// check we have a path
ParameterCheck.mandatoryString("path", path);
this.path = path;
this.instruction = instruction;
this.instructionId = instructionId;
}
public String getPath()
{
return this.path;
}
public String getInstruction()
{
return this.instruction;
}
public String getInstructionId()
{
return this.instructionId;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (path=").append(this.path);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
buffer.append(" description=").append(this.description);
buffer.append(" descriptionId=").append(this.descriptionId);
buffer.append(" instruction=").append(this.instruction);
buffer.append(" instructionId=").append(this.instructionId).append(")");
return buffer.toString();
}
}
/**
* Represents the configuration of a conditional page in a wizard
* i.e. a &lt;page&gt; element that is placed within a &lt;condition&gt;
* element.
*/
public static class ConditionalPageConfig extends PageConfig
{
protected String condition;
public ConditionalPageConfig(String path, String condition,
String title, String titleId,
String description, String descriptionId,
String instruction, String instructionId)
{
super(path, title, titleId, description, descriptionId, instruction, instructionId);
// check we have a path
ParameterCheck.mandatoryString("condition", condition);
this.condition = condition;
}
public String getCondition()
{
return this.condition;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (path=").append(this.path);
buffer.append(" condition=").append(this.condition);
buffer.append(" title=").append(this.title);
buffer.append(" titleId=").append(this.titleId);
buffer.append(" description=").append(this.description);
buffer.append(" descriptionId=").append(this.descriptionId);
buffer.append(" instruction=").append(this.instruction);
buffer.append(" instructionId=").append(this.instructionId).append(")");
return buffer.toString();
}
}
/**
* Represents the configuration of a step in a wizard
* i.e. the &lt;step&gt; element.
*/
public static class StepConfig
{
protected String name;
protected PageConfig defaultPage;
protected List<ConditionalPageConfig> conditionalPages =
new ArrayList<ConditionalPageConfig>(3);
public StepConfig(String name)
{
// check we have a name
ParameterCheck.mandatoryString("name", name);
this.name = name;
}
public String getName()
{
return this.name;
}
public void setDefaultPage(PageConfig page)
{
this.defaultPage = page;
}
public PageConfig getDefaultPage()
{
return this.defaultPage;
}
public boolean hasConditionalPages()
{
return (this.conditionalPages.size() > 0);
}
public void addConditionalPage(ConditionalPageConfig conditionalPage)
{
this.conditionalPages.add(conditionalPage);
}
public List<ConditionalPageConfig> getConditionalPages()
{
return this.conditionalPages;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" (name=").append(this.name);
buffer.append(" defaultPage=").append(this.defaultPage);
buffer.append(" conditionalPages=").append(this.conditionalPages).append(")");
return buffer.toString();
}
}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.config;
import java.util.Iterator;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.xml.elementreader.ConfigElementReader;
import org.alfresco.web.config.WizardsConfigElement.ConditionalPageConfig;
import org.alfresco.web.config.WizardsConfigElement.PageConfig;
import org.alfresco.web.config.WizardsConfigElement.StepConfig;
import org.dom4j.Element;
/**
* Custom element reader to parse config for wizards
*
* @author gavinc
*/
public class WizardsElementReader implements ConfigElementReader
{
public static final String ELEMENT_WIZARDS = "wizards";
public static final String ELEMENT_WIZARD = "wizard";
public static final String ELEMENT_STEP = "step";
public static final String ELEMENT_PAGE = "page";
public static final String ELEMENT_CONDITION = "condition";
public static final String ATTR_NAME = "name";
public static final String ATTR_MANAGED_BEAN = "managed-bean";
public static final String ATTR_TITLE = "title";
public static final String ATTR_TITLE_ID = "title-id";
public static final String ATTR_DESCRIPTION = "description";
public static final String ATTR_DESCRIPTION_ID = "description-id";
public static final String ATTR_INSTRUCTION = "instruction";
public static final String ATTR_INSTRUCTION_ID = "instruction-id";
public static final String ATTR_IF = "if";
public static final String ATTR_PATH = "path";
/**
* @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element)
*/
public ConfigElement parse(Element element)
{
WizardsConfigElement configElement = null;
if (element != null)
{
String elementName = element.getName();
if (elementName.equals(ELEMENT_WIZARDS) == false)
{
throw new ConfigException("WizardsElementReader can only parse " +
ELEMENT_WIZARDS + "elements, the element passed was '" +
elementName + "'");
}
configElement = new WizardsConfigElement();
// go through the items to show
Iterator<Element> items = element.elementIterator(ELEMENT_WIZARD);
while (items.hasNext())
{
Element wizard = items.next();
String name = wizard.attributeValue(ATTR_NAME);
String bean = wizard.attributeValue(ATTR_MANAGED_BEAN);
String title = wizard.attributeValue(ATTR_TITLE);
String titleId = wizard.attributeValue(ATTR_TITLE_ID);
String description = wizard.attributeValue(ATTR_DESCRIPTION);
String descriptionId = wizard.attributeValue(ATTR_DESCRIPTION_ID);
// create the wizard config object
WizardsConfigElement.WizardConfig wizardCfg = new WizardsConfigElement.WizardConfig(
name, bean, title, titleId, description, descriptionId);
Iterator<Element> steps = wizard.elementIterator(ELEMENT_STEP);
while (steps.hasNext())
{
StepConfig stepCfg = parseStep(steps.next());
wizardCfg.addStep(stepCfg);
}
configElement.addWizard(wizardCfg);
}
}
return configElement;
}
/**
* Parses the given element which represents a step in a wizard
*
* @param step The Element representing the step
* @return A StepConfig object
*/
protected StepConfig parseStep(Element step)
{
// get the name of the step and create the config object
StepConfig stepCfg = new StepConfig(step.attributeValue(ATTR_NAME));
// find and parse the default page
Element defaultPageElem = step.element(ELEMENT_PAGE);
if (defaultPageElem != null)
{
String path = defaultPageElem.attributeValue(ATTR_PATH);
String title = defaultPageElem.attributeValue(ATTR_TITLE);
String titleId = defaultPageElem.attributeValue(ATTR_TITLE_ID);
String description = defaultPageElem.attributeValue(ATTR_DESCRIPTION);
String descriptionId = defaultPageElem.attributeValue(ATTR_DESCRIPTION_ID);
String instruction = defaultPageElem.attributeValue(ATTR_INSTRUCTION);
String instructionId = defaultPageElem.attributeValue(ATTR_INSTRUCTION_ID);
// create and set the page config on the step
stepCfg.setDefaultPage(new PageConfig(path, title, titleId, description,
descriptionId, instruction, instructionId));
}
// find and parse any conditions that are present
Iterator<Element> conditions = step.elementIterator(ELEMENT_CONDITION);
while (conditions.hasNext())
{
Element conditionElem = conditions.next();
String ifAttr = conditionElem.attributeValue(ATTR_IF);
Element conditionalPageElem = conditionElem.element(ELEMENT_PAGE);
if (conditionalPageElem == null)
{
throw new ConfigException("A condition in step '" + stepCfg.getName() +
"' does not have a containing <page> element");
}
String path = conditionalPageElem.attributeValue(ATTR_PATH);
String title = conditionalPageElem.attributeValue(ATTR_TITLE);
String titleId = conditionalPageElem.attributeValue(ATTR_TITLE_ID);
String description = conditionalPageElem.attributeValue(ATTR_DESCRIPTION);
String descriptionId = conditionalPageElem.attributeValue(ATTR_DESCRIPTION_ID);
String instruction = conditionalPageElem.attributeValue(ATTR_INSTRUCTION);
String instructionId = conditionalPageElem.attributeValue(ATTR_INSTRUCTION_ID);
// create and add the page to the step
stepCfg.addConditionalPage(new ConditionalPageConfig(path, ifAttr, title,
titleId, description, descriptionId, instruction, instructionId));
}
return stepCfg;
}
}

View File

@@ -17,8 +17,8 @@
package org.alfresco.web.ui.repo.component.property; package org.alfresco.web.ui.repo.component.property;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.faces.component.NamingContainer; import javax.faces.component.NamingContainer;
@@ -120,18 +120,18 @@ public class UIPropertySheet extends UIPanel implements NamingContainer
if (itemsToDisplay != null) if (itemsToDisplay != null)
{ {
List<ItemConfig> itemsToRender = null; Collection<ItemConfig> itemsToRender = null;
if (this.getMode().equalsIgnoreCase(EDIT_MODE)) if (this.getMode().equalsIgnoreCase(EDIT_MODE))
{ {
itemsToRender = itemsToDisplay.getEditableItemsToShow(); itemsToRender = itemsToDisplay.getEditableItemsToShow().values();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Items to render: " + itemsToDisplay.getEditableItemNamesToShow()); logger.debug("Items to render: " + itemsToDisplay.getEditableItemNamesToShow());
} }
else else
{ {
itemsToRender = itemsToDisplay.getItemsToShow(); itemsToRender = itemsToDisplay.getItemsToShow().values();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Items to render: " + itemsToDisplay.getItemNamesToShow()); logger.debug("Items to render: " + itemsToDisplay.getItemNamesToShow());
@@ -439,10 +439,10 @@ public class UIPropertySheet extends UIPanel implements NamingContainer
* in an external config file. * in an external config file.
* *
* @param context JSF context * @param context JSF context
* @param properties List of properties to render (driven from configuration) * @param properties Collection of properties to render (driven from configuration)
* @throws IOException * @throws IOException
*/ */
private void createComponentsFromConfig(FacesContext context, List<ItemConfig> items) private void createComponentsFromConfig(FacesContext context, Collection<ItemConfig> items)
throws IOException throws IOException
{ {
// ********************************** // **********************************

View File

@@ -0,0 +1,78 @@
<alfresco-config>
<plug-ins>
<element-readers>
<element-reader element-name="dialogs" class="org.alfresco.web.config.DialogsElementReader"/>
<element-reader element-name="wizards" class="org.alfresco.web.config.WizardsElementReader"/>
</element-readers>
</plug-ins>
<config evalutor="string-compare" condition="Dialogs">
<dialog-container>/jsp/dialog/container.jsp</dialog-container>
<dialogs>
<dialog name="createSpace" page="/jsp/dialog/create-space.jsp" managed-bean="NewSpaceDialog"
title-id="create_space_title" description-id="create_space_description"
actions-config-id="space-actions" />
<dialog name="spaceDetails" page="/jsp/dialog/space-details.jsp" managed-bean="SpaceDetailsDialog"
title="Space Details Dialog" description="Space Details Dialog Decsription"
actions-config-id="space-actions" />
</dialogs>
</config>
<config evalutor="string-compare" condition="Wizards">
<wizard-container>/jsp/wizard/container.jsp</wizard-container>
<wizards>
<!-- example wizard -->
<wizard name="exampleWizard" managed-bean="ExampleWizard"
title="Example Wizard Title" description="Example Wizard Description">
<step name="details">
<page path="/jsp/wizard/example/details.jsp"
title="Step Title" description="Step Description"
instruction="Step Instruction" />
</step>
<step name="summary">
<page path="/jsp/wizard/example/summary.jsp"
title="Summary Title" description="Summary Description"
instruction="Click Finish" />
</step>
</wizard>
<!-- Definition of an advanced space wizard -->
<wizard name="createSpace" managed-bean="AdvancedSpaceWizard"
title-id="advanced_space_details_title"
description-id="advanced_space_details_description">
<step name="details">
<page path="/jsp/wizard/new-space/create-from.jsp"
title-id="create_space_details_title"
description-id="create_space_details_desc"
instruction-id="create_space_details_instruction" />
</step>
<step name="properties">
<condition if="#{AdvancedSpaceWizard.createFrom == 'template'}">
<page path="/jsp/wizard/new-space/from-template.jsp"
title-id="create_space_template_title"
description-id="create_space_template_desc"
instruction-id="create_space_template_instruction" />
</condition>
<page path="/jsp/wizard/new-space/from-scratch.jsp"
title-id="create_space_scratch_title"
description-id="create_space_scratch_desc"
instruction-id="create_space_scratch_instruction" />
</step>
<step name="summary">
<page path="/jsp/wizard/new-space/summary.jsp"
title-id="create_space_summary_title"
description-id="create_space_summary_desc"
instruction-id="create_space_summary_instruction" />
</step>
</wizard>
</wizards>
</config>
</alfresco-config>

View File

@@ -76,4 +76,20 @@
</views> </views>
</config> </config>
<config evaluator="string-compare" condition="space-aspect">
<property-sheet>
<show-property name="size" readOnly="true" />
<show-property name="icon" readOnly="true" showInEditMode="false" />
</property-sheet>
</config>
<config evalutor="string-compare" condition="Dialogs">
<dialog-container>/custom/my-container.jsp</dialog-container>
<dialogs>
<dialog name="createSpace" page="/custom/my-create-space.jsp" managed-bean="MyNewSpaceDialog"
title-id="create_space_title" description-id="create_space_description" />
</dialogs>
</config>
</alfresco-config> </alfresco-config>