diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index bf61efd79f..56c930502e 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -2008,3 +2008,45 @@ SiteCollaborator=Site Collaborator SiteContributor=Site Contributor sites_space_warning=This space is managed by Alfresco Share. Please use the Alfresco Share application to work with content within this space and any sub-spaces. +# Composite conditions +select_composite_condition=Select Composite Condition +enter_text_condition=Enter condition parameters for a text property +enter_integer_condition=Enter condition parameters for an integer-valued property +enter_date_condition=Enter condition parameters for a date-valued property +enter_boolean_condition=Enter condition parameters for a boolean-valued property +select_default_qname=Select Default QName +composite_condition_page_description=Create a condition by combining several others +composite_condition_page_title=Create Composite Condition +composite_condition_page_selected=Selected conditions to be combined By +composite_condition_page_or=OR +text_property_condition_property=Property name (e.g. cm:description) +integer_property_condition_property=Property name (e.g. my:count) +date_property_condition_property=Property name (e.g. cm:created) +property_condition_operation=Value of the property +property_condition_value=Value of the property +property_condition_operation=Operation +property_condition_equals=Equals To +property_condition_contains=Contains +property_condition_beginswith=Begins With +property_condition_endswith=Ends With +property_condition_greaterthan=Greater Than +property_condition_greaterthanequals=Greater Than Or Equals +property_condition_lessthan=Less Than +property_condition_lessthanequals=Less Than or Equals +property_date_condition_equals=Equals To +property_date_condition_greaterthan=Is After +property_date_condition_greaterthanequals=Is After or On +property_date_condition_lessthan=Is Before +property_date_condition_lessthanequals=Is Before or On +property_condition_invalid=Invalid Operation +condition_compare_text_property_value=Text Property ''{0}'' {1} ''{2}'' +condition_compare_text_property_value_not=Text Property ''{0}'' NOT {1} ''{2}'' +condition_compare_integer_property_value=Integer Property ''{0}'' {1} ''{2}'' +condition_compare_integer_property_value_not=Integer Property ''{0}'' NOT {1} ''{2}'' +condition_compare_date_property_value=Date Property ''{0}'' {1} ''{2}'' +condition_compare_date_property_value_not=Date Property ''{0}'' NOT {1} ''{2}'' +condition_compare_boolean_property_value=Boolean Property ''{0}'' {1} ''{2}'' +condition_compare_boolean_property_value_not=Boolean Property ''{0}'' NOT {1} ''{2}'' +condition_composite_summary=Composite Condition ({0} Conditions {1}) +condition_composite_summary_not=Composite Condition ({0} Conditions {1} and Inverted) +condition_composite_error=Composite Condition (ERROR) diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index c48767d701..eebefc2410 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -400,6 +400,10 @@ + + + + diff --git a/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java b/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java index 873d68b806..6384c349ba 100644 --- a/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java +++ b/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java @@ -697,6 +697,7 @@ public abstract class BaseActionWizard extends BaseWizardBean { // use the built in JSF support for retrieving the object for the // row that was clicked by the user + @SuppressWarnings("unchecked") Map actionToRemove = (Map)this.allActionsDataModel.getRowData(); this.allActionsProperties.remove(actionToRemove); @@ -951,6 +952,7 @@ public abstract class BaseActionWizard extends BaseWizardBean { try { + @SuppressWarnings("unchecked") Class klass = Class.forName(handlerClass); IHandler handler = (IHandler)klass.newInstance(); this.actionHandlers.put(actionName, handler); @@ -1046,6 +1048,15 @@ public abstract class BaseActionWizard extends BaseWizardBean return aspects; } + public boolean isFinishButtonDisabled() + { + if (emailRecipients != null) + { + return emailRecipients.isEmpty(); + } + return true; + } + // ------------------------------------------------------------------------------ // Inner classes @@ -1092,7 +1103,7 @@ public abstract class BaseActionWizard extends BaseWizardBean private String name; private String authority; } - + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); diff --git a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java index e645dc6ec7..b7daed2da4 100644 --- a/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java +++ b/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java @@ -35,9 +35,11 @@ import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.UIContextService; +import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIActionLink; import org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem; @@ -64,6 +66,8 @@ public class ClipboardBean implements Serializable /** Current state of the clipboard items */ private List items = new ArrayList(4); + transient private NodeService nodeService; + // ------------------------------------------------------------------------------ // Bean property getters and setters @@ -84,7 +88,21 @@ public class ClipboardBean implements Serializable this.items = items; } + public void setNodeService(NodeService nodeService) + { + + this.nodeService = nodeService; + } + private NodeService getNodeService() + { + if (nodeService == null) + { + nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService(); + } + return nodeService; + } + // ------------------------------------------------------------------------------ // Navigation action event handlers @@ -158,6 +176,12 @@ public class ClipboardBean implements Serializable List toRemove = new ArrayList(); for (ClipboardItem item : this.items) { + if (!getNodeService().exists(item.getNodeRef())) + { + toRemove.add(item); + continue; + } + if (performClipboardOperation(item, action) == true) { // if cut operation then remove item from the clipboard @@ -202,8 +226,7 @@ public class ClipboardBean implements Serializable } catch (Throwable err) { - Utils.addErrorMessage(Application.getMessage(context, - MSG_ERROR_PASTE) + err.getMessage(), err); + Utils.addErrorMessage(Application.getMessage(context, MSG_ERROR_PASTE) + err.getMessage(), err); } } diff --git a/source/java/org/alfresco/web/bean/rules/CreateCompositeRuleWizard.java b/source/java/org/alfresco/web/bean/rules/CreateCompositeRuleWizard.java new file mode 100644 index 0000000000..7b600259c6 --- /dev/null +++ b/source/java/org/alfresco/web/bean/rules/CreateCompositeRuleWizard.java @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2005-2008 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.web.bean.rules; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; +import javax.faces.model.DataModel; +import javax.faces.model.ListDataModel; +import javax.faces.model.SelectItem; + +import org.alfresco.config.Config; +import org.alfresco.config.ConfigService; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.actions.IHandler; +import org.alfresco.web.bean.rules.handlers.BaseConditionHandler; +import org.alfresco.web.bean.rules.handlers.CompositeConditionHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class CreateCompositeRuleWizard extends CreateRuleWizard +{ + private static final Log logger = LogFactory.getLog(CreateCompositeRuleWizard.class); + + private List compositeConditions; + + // Right now the UI only supports one level of recursion, although the + // backend supports unlimited recursion for composites. + // This limitation is introduced by the fact that we are have two "current" + // conditions - either normal condition, or composite conditions + // basically, the UI will have to store conditions in a more native way + // (instead of DataModel) to get unlimited number of composite conditions + // recursing + protected DataModel currentCompositeConditionsDataModel; + protected List> currentCompositeConditionPropertiesList; + + private boolean addingCompositeCondition; + + public CreateCompositeRuleWizard() + { + // TODO Auto-generated constructor stub + } + + @Override + public void init(Map parameters) + { + super.init(parameters); + + this.setAddingCompositeCondition(false); + this.currentCompositeConditionsDataModel = null; + this.currentCompositeConditionPropertiesList = null; + + } + + public void setupCompositeConditionsMode() + { + this.setAddingCompositeCondition(true); + this.currentCompositeConditionsDataModel = new ListDataModel(); + this.currentCompositeConditionPropertiesList = new ArrayList>(); + + } + + private void clearCompositeConditionMode() + { + // reset the action drop down + this.selectedCondition = null; + // this.currentConditionProperties = null; + this.currentCompositeConditionsDataModel = null; + this.currentCompositeConditionPropertiesList = null; + this.setAddingCompositeCondition(false); + + } + + /** + * Returns the properties for all the conditions as a JSF DataModel + * + * @return JSF DataModel representing the condition properties + */ + public DataModel getAllCompositeConditionsDataModel() + { + if (this.currentCompositeConditionsDataModel == null) + { + this.currentCompositeConditionsDataModel = new ListDataModel(); + } + + this.currentCompositeConditionsDataModel.setWrappedData(this.currentCompositeConditionPropertiesList); + + return this.currentCompositeConditionsDataModel; + } + + /** + * Displays the settings page for the current condition being added (if + * required) + */ + @Override + public void promptForConditionValues() + { + if (CompositeConditionHandler.NAME.equals(this.selectedCondition)) + { + setupCompositeConditionsMode(); + } + + super.promptForConditionValues(); + } + + public void finishAddingCompositeCondition() + { + if (logger.isDebugEnabled()) + logger.debug("Finishing Adding Composite Condition."); + + // reset the effective chosen condition to composite-condition + this.selectedCondition = CompositeConditionHandler.NAME; + + FacesContext context = FacesContext.getCurrentInstance(); + returnViewId = getWizardContainerViewId(context); + + printConditionState(); + + if (logger.isDebugEnabled()) + logger.debug("\tAdding Condition '" + selectedCondition + "'"); + + IHandler handler = this.conditionHandlers.get(this.selectedCondition); + + // creating object temporarily so we can pass it to + // CompositeConditionHandler + // Map newCompositeCondition = new HashMap(); + currentConditionProperties.put(CompositeConditionHandler.PROP_COMPOSITE_CONDITION, + (Serializable) this.currentCompositeConditionPropertiesList); + currentConditionProperties.put(PROP_CONDITION_NAME, this.selectedCondition); + + // this is called from the actions page so there must be a handler + // present so there's no need to check for null + String summary = handler.generateSummary(context, this, currentConditionProperties); + + if (summary != null) + { + currentConditionProperties.put(PROP_CONDITION_SUMMARY, summary); + } + if (logger.isDebugEnabled()) + logger.debug("Generated Summary - [" + summary + "] + selectedCondition " + this.selectedCondition); + + if (editingCondition == false) + { + this.allConditionsPropertiesList.add(currentConditionProperties); + } + clearCompositeConditionMode(); + // refresh the wizard + goToPage(context, this.returnViewId); + } + + private String getWizardContainerViewId(FacesContext context) + { + String viewId = null; + ConfigService configSvc = Application.getConfigService(context); + Config globalConfig = configSvc.getGlobalConfig(); + if (globalConfig != null) + { + viewId = globalConfig.getConfigElement("wizard-container").getValue(); + } + else + { + logger.error("plain-dialog-container configuraion setting is not found"); + } + return viewId; + } + + @Override + public void cancelAddCondition() + { + if (isAddingCompositeCondition()) + { + //don't clear when editing, since we are looking at a REFERENCE to an existing condition + if (this.editingCondition == false) { + this.currentConditionProperties.clear(); + } + // reset the action drop down + this.selectedCondition = null; + IHandler handler = this.conditionHandlers.get(CompositeConditionHandler.NAME); + goToPage(FacesContext.getCurrentInstance(), handler.getJSPPath()); + } + else + { + super.cancelAddCondition(); + return; + } + + } + + /** + * Adds the condition just setup by the user to the list of composite + * conditions This gathers the composite conditions in the + */ + @Override + public void addCondition() + { + if (!isAddingCompositeCondition()) + { + super.addCondition(); + printConditionState(); + return; + } + + if (logger.isDebugEnabled()) + logger.debug("Adding Condition to Composite Condition. "); + + FacesContext context = FacesContext.getCurrentInstance(); + + // this is called from the actions page so there must be a handler + // present so there's no need to check for null + IHandler handler = this.conditionHandlers.get(this.selectedCondition); + + if (handler != null) + { + String summary = handler.generateSummary(context, this, this.currentConditionProperties); + this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, summary); + } + else + { + if (logger.isWarnEnabled()) + logger.warn("No Summary could be generated for rule condition " + this.selectedCondition); + + this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, "ERROR - No Summary for " + this.selectedCondition); + } + + if (editingCondition == false) + { + //this check is needed to prevent an condition when you are editing a composite, to prevent it from adding twice + currentCompositeConditionPropertiesList.add(this.currentConditionProperties); + if (logger.isDebugEnabled()) + logger.debug("\tAdded condition to Composite condition."); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("\tEdited composite condition. "); + //editingCondition = false; + } + + this.currentConditionProperties = new HashMap(3); + + // resetting it for composite condition + // TODO: this is not persistent currently, which causes a minor bug + this.currentConditionProperties.put(PROP_CONDITION_NAME, CompositeConditionHandler.NAME); + this.currentConditionProperties.put(BaseConditionHandler.PROP_CONDITION_NOT, Boolean.FALSE); + + // refresh the wizard + printConditionState(); + goToPage(context, this.returnViewId); + + } + + /** + * Sets up the context for editing existing composite condition values + */ + @SuppressWarnings("unchecked") + public void editCondition() + { + this.editingCondition = true; + + if (logger.isDebugEnabled()) + logger.debug("Editing Conditions. isAddingCompositeConditions - " + isAddingCompositeCondition()); + + //if user is on main conditions screen, check if the condition to be edited is a composite condition + if (!isAddingCompositeCondition()) + { + Map condition = (Map) this.allConditionsDataModel.getRowData(); + + if (condition.get(PROP_CONDITION_NAME).equals(CompositeConditionHandler.NAME)) + { + logger.debug("Composite Condition selected, enabling CompositeCondition Mode"); + currentCompositeConditionPropertiesList = (List>) condition + .get(CompositeConditionHandler.PROP_COMPOSITE_CONDITION); + addingCompositeCondition = true; + } + super.editCondition(condition ); + return; + } + else + { + Map subCondition = (Map) currentCompositeConditionsDataModel.getRowData(); + super.editCondition(subCondition); + } + } + + + + public List getCompositeConditions() + { + if (this.compositeConditions == null) + { + this.compositeConditions = new ArrayList(); + List tempConditions = this.getConditions(); // loads up the conditions + for (SelectItem item : tempConditions) + { + if (!((item.getValue().equals(CompositeConditionHandler.NAME)) || (item.getValue().equals("no-condition")))) + { + this.compositeConditions.add(item); + } + } + } + + return this.compositeConditions; + } + + protected boolean isAddingCompositeCondition() + { + return addingCompositeCondition; + } + + protected void setAddingCompositeCondition(boolean addingCompositeCondition) + { + if (logger.isDebugEnabled()) + logger.debug("Setting addingCompositeCondition to " + addingCompositeCondition); + + this.addingCompositeCondition = addingCompositeCondition; + } + + /** + * Removes the requested condition from the list + */ + public void removeCondition() + { + if (!isAddingCompositeCondition()) + { + super.removeCondition(); + return; + } + + if (logger.isDebugEnabled()) + logger.debug("Removing Composite Conditions"); + + // use the built in JSF support for retrieving the object for the + // row that was clicked by the user + Map conditionToRemove = (Map) this.currentCompositeConditionsDataModel.getRowData(); + this.currentCompositeConditionPropertiesList.remove(conditionToRemove); + // reset the action drop down + this.selectedCondition = null; + + // refresh the wizard + FacesContext context = FacesContext.getCurrentInstance(); + goToPage(context, context.getViewRoot().getViewId()); + } + + protected void printConditionState() + { + if (logger.isDebugEnabled()) + { + logger.debug("\t\t*** GLOBAL ***"); + + logger.debug("\t\tallConditionsProperties"); + if (allConditionsPropertiesList == null) + { + logger.debug("\t\t\tempty"); + } + else + { + for (Object obj : allConditionsPropertiesList) + { + logger.debug("\t\t\t" + obj.toString()); + } + } + + logger.debug("\t\t*** COMPOSITE ***"); + logger.debug("\t\taddingCompositeCondition " + addingCompositeCondition); + + logger.debug("\t\tcurrentCompositeConditionsProperties"); + if (currentCompositeConditionPropertiesList == null) + { + logger.debug("\t\t\t EMPTY"); + } + else + { + int i = 1; + for (Map cond : currentCompositeConditionPropertiesList) + { + logger.debug("\t\t\tCondition" + i++); + + for (String key : cond.keySet()) + { + logger.debug("\t\t\t\tkey - {" + key + "} value - {" + cond.get(key) + "}"); + } + } + } + + logger.debug("\t\t*** BOTH ***"); + + logger.debug("\t\tcurrentConditionsProperties"); + if (currentConditionProperties == null) + { + logger.debug("\t\t\t EMPTY"); + } + else + { + for (String key : this.currentConditionProperties.keySet()) + { + logger.debug("\t\t\tkey - {" + key + "} value - {" + this.currentConditionProperties.get(key) + "}"); + } + } + } + } +} diff --git a/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java b/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java index 3bb0d909f4..10aa3eaec3 100644 --- a/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java +++ b/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java @@ -18,7 +18,7 @@ * 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 + * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ @@ -46,6 +46,7 @@ import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionCondition; import org.alfresco.service.cmr.action.ActionConditionDefinition; import org.alfresco.service.cmr.action.CompositeAction; +import org.alfresco.service.cmr.action.CompositeActionCondition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.rule.Rule; import org.alfresco.service.cmr.rule.RuleService; @@ -57,6 +58,7 @@ import org.alfresco.web.bean.actions.IHandler; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.rules.handlers.BaseConditionHandler; +import org.alfresco.web.bean.rules.handlers.CompositeConditionHandler; import org.alfresco.web.data.IDataContainer; import org.alfresco.web.data.QuickSort; import org.alfresco.web.ui.common.Utils; @@ -74,25 +76,33 @@ public class CreateRuleWizard extends BaseActionWizard protected static final String PROP_CONDITION_NAME = "conditionName"; protected static final String PROP_CONDITION_SUMMARY = "conditionSummary"; - + transient private RuleService ruleService; protected RulesDialog rulesDialog; - - private List modelTypes; - private List mimeTypes; + + private List modelTypes; //this is for subtype condition + private List mimeTypes; //for checking mime types condition private List types; + private List conditions; - - protected Map conditionHandlers; + + protected Map conditionHandlers; //contains UI handlers, i.e. classes that know which JSP to to forward to + + //This is where all the current condition properties go. When addConditions is called, + //these are saved into allConditionsPropertiesList protected Map currentConditionProperties; - protected List> allConditionsProperties; transient protected DataModel allConditionsDataModel; - + + // protected List> allConditionsProperties; + //allConditionsProperties needs to be able to store both Map and List> + //(for composite conditions) + protected List> allConditionsPropertiesList; + protected String title; protected String description; protected String type; - protected String condition; + protected String selectedCondition; protected boolean runInBackground; protected boolean applyToSubSpaces; protected boolean editingCondition; @@ -111,21 +121,23 @@ public class CreateRuleWizard extends BaseActionWizard this.title = null; this.description = null; this.type = "inbound"; - this.condition = null; + this.selectedCondition = null; this.applyToSubSpaces = false; this.runInBackground = false; this.ruleDisabled = false; this.conditions = null; - this.allConditionsProperties = new ArrayList>(); + this.allConditionsPropertiesList = new ArrayList>(); initialiseConditionHandlers(); } @Override - protected String finishImpl(FacesContext context, String outcome) - throws Exception + protected String finishImpl(FacesContext context, String outcome) throws Exception { + if (logger.isDebugEnabled()) + logger.debug("finishImpl called - saving rules"); + // get hold of the space the rule will apply to and make sure // it is actionable Node currentSpace = this.browseBean.getActionSpace(); @@ -156,38 +168,34 @@ public class CreateRuleWizard extends BaseActionWizard boolean disabled = true; int step = Application.getWizardManager().getCurrentStep(); - switch(step) + switch (step) { - case 1: - { - disabled = (this.allConditionsDataModel == null || - this.allConditionsDataModel.getRowCount() == 0); - break; - } - case 2: - { - disabled = (this.allActionsDataModel == null || - this.allActionsDataModel.getRowCount() == 0); - break; - } - case 3: - { - disabled = (this.title == null || this.title.length() == 0); - break; - } + case 1: + { + disabled = (this.allConditionsDataModel == null || this.allConditionsDataModel.getRowCount() == 0); + break; } - + case 2: + { + disabled = (this.allActionsDataModel == null || this.allActionsDataModel.getRowCount() == 0); + break; + } + case 3: + { + disabled = (this.title == null || this.title.length() == 0); + break; + } + } + return disabled; } @Override public boolean getFinishButtonDisabled() { - if (this.allActionsDataModel != null && - this.allActionsDataModel.getRowCount() > 0 && - this.allConditionsDataModel != null && - this.allConditionsDataModel.getRowCount() > 0 && - this.title != null && this.title.length() > 0) + if (this.allActionsDataModel != null && this.allActionsDataModel.getRowCount() > 0 + && this.allConditionsDataModel != null && this.allConditionsDataModel.getRowCount() > 0 + && this.title != null && this.title.length() > 0) { return false; } @@ -204,7 +212,7 @@ public class CreateRuleWizard extends BaseActionWizard { // create the summary using all the conditions StringBuilder conditionsSummary = new StringBuilder(); - for (Map props : this.allConditionsProperties) + for (Map props : this.allConditionsPropertiesList) { conditionsSummary.append(Utils.encode((String)props.get(PROP_CONDITION_SUMMARY))); conditionsSummary.append("
"); @@ -223,35 +231,35 @@ public class CreateRuleWizard extends BaseActionWizard String backgroundYesNo = this.runInBackground ? bundle.getString("yes") : bundle.getString("no"); String subSpacesYesNo = this.applyToSubSpaces ? bundle.getString("yes") : bundle.getString("no"); String ruleDisabledYesNo = this.ruleDisabled ? bundle.getString("yes") : bundle.getString("no"); - - return buildSummary( - new String[] {bundle.getString("rule_type"), bundle.getString("name"), bundle.getString("description"), - bundle.getString("apply_to_sub_spaces"), bundle.getString("run_in_background"), bundle.getString("rule_disabled"), - bundle.getString("conditions"), bundle.getString("actions")}, - new String[] {this.type, Utils.encode(this.title), Utils.encode(this.description), - subSpacesYesNo, backgroundYesNo, ruleDisabledYesNo, - conditionsSummary.toString(), actionsSummary.toString()}); + + return buildSummary(new String[] + { bundle.getString("rule_type"), bundle.getString("name"), bundle.getString("description"), + bundle.getString("apply_to_sub_spaces"), bundle.getString("run_in_background"), + bundle.getString("rule_disabled"), bundle.getString("conditions"), bundle.getString("actions") }, + new String[] + { this.type, Utils.encode(this.title), Utils.encode(this.description), subSpacesYesNo, backgroundYesNo, + ruleDisabledYesNo, conditionsSummary.toString(), actionsSummary.toString() }); } - + @Override protected String getErrorMessageId() { return "error_rule"; } - + protected CompositeAction getCompositeAction(Rule rule) { - // Get the composite action - Action ruleAction = rule.getAction(); - if (ruleAction == null) - { - throw new AlfrescoRuntimeException("Rule does not have associated action."); - } - else if ((ruleAction instanceof CompositeAction) == false) - { - throw new AlfrescoRuntimeException("Rules with non-composite actions are not currently supported by the UI"); - } - return (CompositeAction)ruleAction; + // Get the composite action + Action ruleAction = rule.getAction(); + if (ruleAction == null) + { + throw new AlfrescoRuntimeException("Rule does not have associated action."); + } + else if ((ruleAction instanceof CompositeAction) == false) + { + throw new AlfrescoRuntimeException("Rules with non-composite actions are not currently supported by the UI"); + } + return (CompositeAction) ruleAction; } // ------------------------------------------------------------------------------ @@ -278,12 +286,12 @@ public class CreateRuleWizard extends BaseActionWizard { this.allConditionsDataModel = new ListDataModel(); } - - this.allConditionsDataModel.setWrappedData(this.allConditionsProperties); - + + this.allConditionsDataModel.setWrappedData(this.allConditionsPropertiesList); + return this.allConditionsDataModel; } - + /** * Returns a list of the types available in the repository * @@ -351,22 +359,22 @@ public class CreateRuleWizard extends BaseActionWizard */ public List getMimeTypes() { - if (this.mimeTypes == null) - { - this.mimeTypes = new ArrayList(50); + if (this.mimeTypes == null) + { + this.mimeTypes = new ArrayList(50); - Map mimeTypes = getMimetypeService().getDisplaysByMimetype(); - for (String mimeType : mimeTypes.keySet()) - { - this.mimeTypes.add(new SelectItem(mimeType, mimeTypes.get(mimeType))); - } + Map mimeTypes = getMimetypeService().getDisplaysByMimetype(); + for (String mimeType : mimeTypes.keySet()) + { + this.mimeTypes.add(new SelectItem(mimeType, mimeTypes.get(mimeType))); + } - // make sure the list is sorted by the values - QuickSort sorter = new QuickSort(this.mimeTypes, "label", true, IDataContainer.SORT_CASEINSENSITIVE); - sorter.sort(); - } + // make sure the list is sorted by the values + QuickSort sorter = new QuickSort(this.mimeTypes, "label", true, IDataContainer.SORT_CASEINSENSITIVE); + sorter.sort(); + } - return this.mimeTypes; + return this.mimeTypes; } /** @@ -381,8 +389,7 @@ public class CreateRuleWizard extends BaseActionWizard for (ActionConditionDefinition ruleConditionDef : ruleConditions) { // add to SelectItem list - this.conditions.add(new SelectItem(ruleConditionDef.getName(), - ruleConditionDef.getTitle())); + this.conditions.add(new SelectItem(ruleConditionDef.getName(), ruleConditionDef.getTitle())); } // make sure the list is sorted by the label @@ -390,8 +397,8 @@ public class CreateRuleWizard extends BaseActionWizard sorter.sort(); // add the "Select a condition" entry at the beginning of the list - this.conditions.add(0, new SelectItem("null", - Application.getMessage(FacesContext.getCurrentInstance(), "select_a_condition"))); + this.conditions.add(0, new SelectItem("null", Application.getMessage(FacesContext.getCurrentInstance(), + "select_a_condition"))); } return this.conditions; @@ -492,7 +499,7 @@ public class CreateRuleWizard extends BaseActionWizard */ public boolean getRuleDisabled() { - return this.ruleDisabled; + return this.ruleDisabled; } /** @@ -500,7 +507,7 @@ public class CreateRuleWizard extends BaseActionWizard */ public void setRuleDisabled(boolean ruleDisabled) { - this.ruleDisabled = ruleDisabled; + this.ruleDisabled = ruleDisabled; } /** @@ -524,7 +531,7 @@ public class CreateRuleWizard extends BaseActionWizard */ public String getCondition() { - return this.condition; + return this.selectedCondition; } /** @@ -532,7 +539,7 @@ public class CreateRuleWizard extends BaseActionWizard */ public void setCondition(String condition) { - this.condition = condition; + this.selectedCondition = condition; } @@ -551,37 +558,45 @@ public class CreateRuleWizard extends BaseActionWizard this.returnViewId = context.getViewRoot().getViewId(); String viewId = null; - HashMap condProps = new HashMap(3); - condProps.put(PROP_CONDITION_NAME, this.condition); - this.currentConditionProperties = condProps; - + this.currentConditionProperties = new HashMap(3); + this.currentConditionProperties.put(PROP_CONDITION_NAME, this.selectedCondition); + this.currentConditionProperties.put(BaseConditionHandler.PROP_CONDITION_NOT, Boolean.FALSE); + // get the handler for the condition, if there isn't one we presume it // is a no-parameter condition - IHandler handler = this.conditionHandlers.get(this.condition); + IHandler handler = this.conditionHandlers.get(this.selectedCondition); if (handler != null) { + if (logger.isDebugEnabled()) + logger.debug("Found Handler for selected condition - '" + this.selectedCondition + "'"); + // setup any UI defaults the condition may have and get the location of // the JSP used to collect the parameters - handler.setupUIDefaults(condProps); + handler.setupUIDefaults(this.currentConditionProperties); viewId = handler.getJSPPath(); + if (logger.isDebugEnabled()) + logger.debug("Handler returned JSP page- '" + viewId + "' Handler Type " + handler.getClass().toString()); } else { + if (logger.isDebugEnabled()) + logger.debug("Did Not Find a handler for selected condition - '" + this.selectedCondition + "'"); + // just add the action to the list and use the title as the summary - ActionConditionDefinition conditionDef = this.getActionService(). - getActionConditionDefinition(this.condition); - condProps.put(PROP_CONDITION_SUMMARY, conditionDef.getTitle()); - condProps.put(BaseConditionHandler.PROP_CONDITION_NOT, Boolean.FALSE); + ActionConditionDefinition conditionDef = this.getActionService() + .getActionConditionDefinition(this.selectedCondition); + this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, conditionDef.getTitle()); + this.currentConditionProperties.put(BaseConditionHandler.PROP_CONDITION_NOT, Boolean.FALSE); // add the no params marker so we can disable the edit action - condProps.put(NO_PARAMS_MARKER, "no-params"); - this.allConditionsProperties.add(condProps); - + this.currentConditionProperties.put(NO_PARAMS_MARKER, "no-params"); + this.allConditionsPropertiesList.add(this.currentConditionProperties); + // come back to the same page we're on now as there are no params to collect viewId = this.returnViewId; } if (logger.isDebugEnabled()) - logger.debug("Added '" + this.condition + "' condition to list"); + logger.debug("Currently creating '" + this.selectedCondition + "' condition"); // go to the page to collect the settings goToPage(context, viewId); @@ -593,53 +608,68 @@ public class CreateRuleWizard extends BaseActionWizard @SuppressWarnings("unchecked") public void editCondition() { - // use the built in JSF support for retrieving the object for the - // row that was clicked by the user - Map conditionToEdit = (Map)this.allConditionsDataModel.getRowData(); - this.condition = (String)conditionToEdit.get(PROP_CONDITION_NAME); - this.currentConditionProperties = conditionToEdit; - + Map conditionToEdit = (Map) this.allConditionsDataModel.getRowData(); + editCondition(conditionToEdit); + } + + protected void editCondition(Map conditionToEdit) + { // set the flag to show we are editing a condition this.editingCondition = true; - + + // use the built in JSF support for retrieving the object for the + // row that was clicked by the user + this.selectedCondition = (String) conditionToEdit.get(PROP_CONDITION_NAME); + this.currentConditionProperties = conditionToEdit; + + if (logger.isDebugEnabled()) + logger.debug("Editing Condition '" + selectedCondition + "'"); + // remember the page we're on FacesContext context = FacesContext.getCurrentInstance(); this.returnViewId = context.getViewRoot().getViewId(); - + // go to the condition page (as there is an edit option visible, // there must be a handler for the condition so we don't check) - goToPage(context, this.conditionHandlers.get(this.condition).getJSPPath()); + goToPage(context, this.conditionHandlers.get(this.selectedCondition).getJSPPath()); } - + /** * Adds the condition just setup by the user to the list of conditions for the rule */ public void addCondition() { FacesContext context = FacesContext.getCurrentInstance(); - + + if (logger.isDebugEnabled()) + logger.debug("Adding Condition '" + selectedCondition + "'"); + + IHandler handler = this.conditionHandlers.get(this.selectedCondition); + // this is called from the actions page so there must be a handler // present so there's no need to check for null - String summary = this.conditionHandlers.get(this.condition).generateSummary( - context, this, this.currentConditionProperties); - + String summary = handler.generateSummary(context, this, this.currentConditionProperties); + if (summary != null) { this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, summary); } - + if (logger.isDebugEnabled()) + logger.debug("Generated Summary - [" + summary + "] + selectedCondition " + this.selectedCondition); + if (this.editingCondition == false) { - this.allConditionsProperties.add(this.currentConditionProperties); + this.allConditionsPropertiesList.add(this.currentConditionProperties); + } - + // reset the action drop down - this.condition = null; - + this.selectedCondition = null; + // refresh the wizard goToPage(context, this.returnViewId); } - + /** * Removes the requested condition from the list */ @@ -647,12 +677,12 @@ public class CreateRuleWizard extends BaseActionWizard { // use the built in JSF support for retrieving the object for the // row that was clicked by the user - Map conditionToRemove = (Map)this.allConditionsDataModel.getRowData(); - this.allConditionsProperties.remove(conditionToRemove); + Map conditionToRemove = (Map) this.allConditionsDataModel.getRowData(); + this.allConditionsPropertiesList.remove(conditionToRemove); // reset the action drop down - this.condition = null; - + this.selectedCondition = null; + // refresh the wizard FacesContext context = FacesContext.getCurrentInstance(); goToPage(context, context.getViewRoot().getViewId()); @@ -669,7 +699,7 @@ public class CreateRuleWizard extends BaseActionWizard } // reset the action drop down - this.condition = null; + this.selectedCondition = null; // refresh the wizard goToPage(FacesContext.getCurrentInstance(), this.returnViewId); @@ -718,8 +748,12 @@ public class CreateRuleWizard extends BaseActionWizard * @param outcome The default outcome * @return The outcome */ + @SuppressWarnings("unchecked") protected String setupRule(FacesContext context, Rule rule, String outcome) { + if (logger.isDebugEnabled()) + logger.debug("Saving Rules - setupRule"); + // setup the rule and add it to the space rule.setTitle(this.title); rule.setDescription(this.description); @@ -729,39 +763,45 @@ public class CreateRuleWizard extends BaseActionWizard CompositeAction compositeAction = this.getActionService().createCompositeAction(); rule.setAction(compositeAction); - + int i = 1; // add all the conditions to the rule - for (Map condParams : this.allConditionsProperties) + for (Object condParamsObj : this.allConditionsPropertiesList) { - String conditionName = (String)condParams.get(PROP_CONDITION_NAME); - this.condition = conditionName; - - // get the condition handler to prepare for the save - Map repoCondParams = new HashMap(); - IHandler handler = this.conditionHandlers.get(this.condition); - if (handler != null) + if (logger.isDebugEnabled()) + logger.debug("Saving Condition " + i++ + " of " + this.allConditionsPropertiesList.size()); + + Map uiConditionParams = (Map) condParamsObj; + + ActionCondition condition = createCondition(uiConditionParams); + + if (condition instanceof CompositeActionCondition) { - handler.prepareForSave(condParams, repoCondParams); + CompositeActionCondition compositeCondition = (CompositeActionCondition) condition; + + List> subconditionProps = (List>) uiConditionParams + .get(CompositeConditionHandler.PROP_COMPOSITE_CONDITION); + int j = 1; + compositeCondition.setORCondition(((Boolean)uiConditionParams.get(CompositeConditionHandler.PROP_CONDITION_OR)).booleanValue()); + compositeCondition.setInvertCondition((((Boolean)uiConditionParams.get(CompositeConditionHandler.PROP_CONDITION_NOT)).booleanValue())); + + for (Map props : subconditionProps) + { + if (logger.isDebugEnabled()) + logger.debug("Saving Composite Condition " + j++ + " of " + subconditionProps.size()); + + compositeCondition.addActionCondition(createCondition(props)); + } } - - // add the condition to the rule - ActionCondition condition = this.getActionService(). - createActionCondition(conditionName); - condition.setParameterValues(repoCondParams); - - // specify whether the condition result should be inverted - Boolean not = (Boolean)condParams.get(BaseConditionHandler.PROP_CONDITION_NOT); - condition.setInvertCondition(((Boolean)not).booleanValue()); - compositeAction.addActionCondition(condition); } // add all the actions to the rule for (Map actionParams : this.allActionsProperties) { - // use the base class version of buildActionParams(), but for this we need + // use the base class version of buildActionParams(), but for this + // we need // to setup the currentActionProperties and action variables - String actionName = (String)actionParams.get(PROP_ACTION_NAME); + String actionName = (String) actionParams.get(PROP_ACTION_NAME); this.action = actionName; // get the action handler to prepare for the save @@ -780,6 +820,38 @@ public class CreateRuleWizard extends BaseActionWizard return outcome; } + + private ActionCondition createCondition(Map uiConditionParams) + { + // get the condition handler to prepare for the save + + String conditionName = (String) uiConditionParams.get(PROP_CONDITION_NAME); + + Map repoCondParams = new HashMap(); + if (logger.isDebugEnabled()) + { + logger.debug("\tSaving " + conditionName); + } + IHandler handler = this.conditionHandlers.get(conditionName); + if (handler != null) + { + handler.prepareForSave(uiConditionParams, repoCondParams); + } + + // add the condition to the rule + ActionCondition condition = this.getActionService().createActionCondition(conditionName); + condition.setParameterValues(repoCondParams); + + // specify whether the condition result should be inverted + Boolean not = (Boolean) uiConditionParams.get(BaseConditionHandler.PROP_CONDITION_NOT); + if (not == null) + { + logger.warn("Property missing NOT parameter value (currently null)"); + not = Boolean.TRUE; + } + condition.setInvertCondition(((Boolean) not).booleanValue()); + return condition; + } /** * Initialises the condition handlers from the current configuration. @@ -803,19 +875,20 @@ public class CreateRuleWizard extends BaseActionWizard String conditionName = child.getAttribute("name"); String handlerClass = child.getAttribute("class"); - if (conditionName != null && conditionName.length() > 0 && - handlerClass != null && handlerClass.length() > 0) + if (conditionName != null && conditionName.length() > 0 && handlerClass != null + && handlerClass.length() > 0) { try { + @SuppressWarnings("unchecked") Class klass = Class.forName(handlerClass); - IHandler handler = (IHandler)klass.newInstance(); + IHandler handler = (IHandler) klass.newInstance(); this.conditionHandlers.put(conditionName, handler); } catch (Exception e) { - throw new AlfrescoRuntimeException("Failed to setup condition handler for '" + - conditionName + "'", e); + throw new AlfrescoRuntimeException("Failed to setup condition handler for '" + conditionName + + "'", e); } } } @@ -837,7 +910,7 @@ public class CreateRuleWizard extends BaseActionWizard in.defaultReadObject(); this.allConditionsDataModel = new ListDataModel(); - this.allConditionsDataModel.setWrappedData(this.allConditionsProperties); + this.allConditionsDataModel.setWrappedData(this.allConditionsPropertiesList); } } diff --git a/source/java/org/alfresco/web/bean/rules/EditRuleWizard.java b/source/java/org/alfresco/web/bean/rules/EditRuleWizard.java index e1fc8e4f02..d0bd3d11d5 100644 --- a/source/java/org/alfresco/web/bean/rules/EditRuleWizard.java +++ b/source/java/org/alfresco/web/bean/rules/EditRuleWizard.java @@ -25,6 +25,7 @@ package org.alfresco.web.bean.rules; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,20 +38,21 @@ import org.alfresco.service.cmr.action.ActionCondition; import org.alfresco.service.cmr.action.ActionConditionDefinition; import org.alfresco.service.cmr.action.ActionDefinition; import org.alfresco.service.cmr.action.CompositeAction; +import org.alfresco.service.cmr.action.CompositeActionCondition; import org.alfresco.service.cmr.rule.Rule; import org.alfresco.web.bean.actions.IHandler; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.rules.handlers.BaseConditionHandler; +import org.alfresco.web.bean.rules.handlers.CompositeConditionHandler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - /** * Bean implementation for the "Edit Rule" wizard * * @author gavinc */ -public class EditRuleWizard extends CreateRuleWizard +public class EditRuleWizard extends CreateCompositeRuleWizard { private static final long serialVersionUID = -7222762769396254445L; @@ -59,6 +61,8 @@ public class EditRuleWizard extends CreateRuleWizard // ------------------------------------------------------------------------------ // Wizard implementation + /* Loads up conditions and actions from the repository + */ @Override public void init(Map parameters) { @@ -84,42 +88,20 @@ public class EditRuleWizard extends CreateRuleWizard // Get the composite action CompositeAction compositeAction = getCompositeAction(rule); - - // populate the conditions list with maps of properties representing each condition - List conditions = compositeAction.getActionConditions(); - for (ActionCondition condition : conditions) - { - this.currentConditionProperties = new HashMap(3); - this.condition = condition.getActionConditionDefinitionName(); - this.currentConditionProperties.put(PROP_CONDITION_NAME, this.condition); - this.currentConditionProperties.put(BaseConditionHandler.PROP_CONDITION_NOT, - Boolean.valueOf(condition.getInvertCondition())); - - IHandler handler = this.conditionHandlers.get(this.condition); - if (handler != null) - { - // use the handler to populate the properties and summary - handler.prepareForEdit(this.currentConditionProperties, - condition.getParameterValues()); - this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, - handler.generateSummary(context, this, this.currentConditionProperties)); - } - else - { - // there's no handler, so we presume it is a no-paramter - // condition, use the condition title as the summary - ActionConditionDefinition conditionDef = this.getActionService(). - getActionConditionDefinition(this.condition); - this.currentConditionProperties.put(PROP_CONDITION_SUMMARY, - conditionDef.getTitle()); - // add the no params marker so we can disable the edit action - this.currentConditionProperties.put(NO_PARAMS_MARKER, "no-params"); - } - - // add the populated currentConditionProperties to the list - this.allConditionsProperties.add(this.currentConditionProperties); - } - + + populateConditions(context, compositeAction); + + populateActions(context, compositeAction); + + // reset the current condition + this.selectedCondition = null; + + // reset the current action + this.action = null; + } + + protected void populateActions(FacesContext context, CompositeAction compositeAction) + { // populate the actions list with maps of properties representing each action List actions = compositeAction.getActions(); for (Action action : actions) @@ -133,28 +115,98 @@ public class EditRuleWizard extends CreateRuleWizard { // use the handler to populate the properties and summary handler.prepareForEdit(this.currentActionProperties, action.getParameterValues()); - this.currentActionProperties.put(PROP_ACTION_SUMMARY, - handler.generateSummary(context, this, this.currentActionProperties)); + this.currentActionProperties.put(PROP_ACTION_SUMMARY, handler.generateSummary(context, this, + this.currentActionProperties)); } else { - // there's no handler, so we presume it is a no-paramter + // there's no handler, so we presume it is a no-parameter // action, use the action title as the summary ActionDefinition actionDef = this.getActionService().getActionDefinition(this.action); this.currentActionProperties.put(PROP_ACTION_SUMMARY, actionDef.getTitle()); // add the no params marker so we can disable the edit action this.currentActionProperties.put(NO_PARAMS_MARKER, "no-params"); } - + // add the populated currentActionProperties to the list this.allActionsProperties.add(this.currentActionProperties); } - - // reset the current condition - this.condition = null; - - // reset the current action - this.action = null; + } + + protected void populateConditions(FacesContext context, CompositeAction compositeAction) + { + // populate the conditions list with maps of properties representing each condition + List conditions = compositeAction.getActionConditions(); + for (ActionCondition toplevel_condition : conditions) + { + this.selectedCondition = toplevel_condition.getActionConditionDefinitionName(); + this.currentConditionProperties = new HashMap(); + + if (logger.isDebugEnabled()) + logger.debug("Preparing for Edit Condition " + this.selectedCondition); + + if (toplevel_condition instanceof CompositeActionCondition) + { + if (logger.isDebugEnabled()) + logger.debug("\tDetected CompositeCondition"); + + CompositeActionCondition compositeCondition = (CompositeActionCondition) toplevel_condition; + this.currentCompositeConditionPropertiesList = new ArrayList>(); + + //TODO: add OR property + + for (ActionCondition subcondition : compositeCondition.getActionConditions()) + { + if (logger.isDebugEnabled()) + logger.debug("\tSetting ... SubConditions " + subcondition.getActionConditionDefinitionName()); + + this.selectedCondition = subcondition.getActionConditionDefinitionName(); + Map subConditionProperties = new HashMap(); + populateProperties(context, subcondition, subConditionProperties); + this.currentCompositeConditionPropertiesList.add(subConditionProperties); + } + + this.selectedCondition = CompositeConditionHandler.NAME; + + this.currentConditionProperties.put(CompositeConditionHandler.PROP_COMPOSITE_CONDITION, + (Serializable) this.currentCompositeConditionPropertiesList); + + populateProperties(context, compositeCondition, currentConditionProperties); + + } else + populateProperties(context, toplevel_condition, this.currentConditionProperties); + + // add the populated currentConditionProperties to the list + this.allConditionsPropertiesList.add(this.currentConditionProperties); + + printConditionState(); + + } + } + + + protected void populateProperties(FacesContext context, ActionCondition condition, + Map uiConditionProperties) + { + uiConditionProperties.put(PROP_CONDITION_NAME, this.selectedCondition); + uiConditionProperties.put(BaseConditionHandler.PROP_CONDITION_NOT, Boolean.valueOf(condition.getInvertCondition())); + + IHandler handler = this.conditionHandlers.get(this.selectedCondition); + if (handler != null) + { + // use the handler to populate the properties and summary + handler.prepareForEdit(uiConditionProperties, condition.getParameterValues()); + uiConditionProperties.put(PROP_CONDITION_SUMMARY, handler + .generateSummary(context, this, uiConditionProperties)); + } else + { + // there's no handler, so we presume it is a no-parameter + // condition, use the condition title as the summary + ActionConditionDefinition conditionDef = this.getActionService().getActionConditionDefinition(this.selectedCondition); + uiConditionProperties.put(PROP_CONDITION_SUMMARY, conditionDef.getTitle()); + // add the no params marker so we can disable the edit action + uiConditionProperties.put(NO_PARAMS_MARKER, "no-params"); + } } @Override diff --git a/source/java/org/alfresco/web/bean/rules/handlers/CompositeConditionHandler.java b/source/java/org/alfresco/web/bean/rules/handlers/CompositeConditionHandler.java new file mode 100644 index 0000000000..e70dda0a7a --- /dev/null +++ b/source/java/org/alfresco/web/bean/rules/handlers/CompositeConditionHandler.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2005-2008 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.web.bean.rules.handlers; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; + +import org.alfresco.repo.action.ActionModel; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.wizard.IWizardBean; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Jean Barmash + * This class has no equivalent evaluator, since it + * + */ +public class CompositeConditionHandler extends BaseConditionHandler +{ + public static final String NAME = "composite-condition"; + public static final String PROP_COMPOSITE_CONDITION = "composite-condition"; + + private static final Log logger = LogFactory.getLog(CompositeConditionHandler.class); + + public static final String PROP_CONDITION_OR = "orconditions"; + + /* (non-Javadoc) + * @see org.alfresco.web.bean.actions.IHandler#generateSummary(javax.faces.context.FacesContext, org.alfresco.web.bean.wizard.IWizardBean, java.util.Map) + */ + public String generateSummary(FacesContext context, IWizardBean wizard, + Map props) + { + List conditionPropertiesList = (List) props.get(PROP_COMPOSITE_CONDITION); + if (conditionPropertiesList == null ) + { + logger.error("Error - composite condition has no sub-conditions"); + + if (logger.isDebugEnabled()) + { + for (String str : props.keySet()) + { + logger.debug("\t key - "+ str + " value " + props.get(str)); + } + } + + return Application.getMessage(context, "condition_composite_error"); + } + + Boolean not = (Boolean) props.get(PROP_CONDITION_NOT); + Boolean orconditions = (Boolean) props.get(PROP_CONDITION_OR); + + String msgId = not.booleanValue() ? "condition_composite_summary_not" : "condition_composite_summary"; + return MessageFormat.format(Application.getMessage(context, msgId), + new Object[] {conditionPropertiesList.size(), orconditions.booleanValue()?"ORed":"ANDed"}); + } + + /* (non-Javadoc) + * @see org.alfresco.web.bean.actions.IHandler#getJSPPath() + */ + public String getJSPPath() + { + return getJSPPath(CompositeConditionHandler.NAME); + } + + /* (non-Javadoc) + * @see org.alfresco.web.bean.actions.IHandler#prepareForEdit(java.util.Map, java.util.Map) + */ + public void prepareForEdit(Map uiConditionProps, + Map repoProps) + { + if (logger.isDebugEnabled()) + logger.debug("Preparing Composite Condition for Edit"); + + Boolean orconditions = (Boolean) repoProps.get(PROP_CONDITION_OR); + if (orconditions == null) + { + if (logger.isWarnEnabled()) + logger.warn("orconditions is NULL, it should not be. Defaulting to false"); + + orconditions = Boolean.FALSE; + } + + uiConditionProps.put(PROP_CONDITION_OR, orconditions); + } + + public void prepareForSave(Map uiConditionProps, + Map repoProps) + { + if (logger.isDebugEnabled()) + logger.debug("Saving Composite Condition"); + + // put the selected category in the condition params + Boolean orconditions = (Boolean)uiConditionProps.get(PROP_CONDITION_OR); + if (orconditions == null) + { + if (logger.isWarnEnabled()) + logger.warn("orconditions is NULL, it should not be. Defaulting to false"); + + orconditions = Boolean.FALSE; + } + + repoProps.put(PROP_CONDITION_OR, orconditions); + } +} diff --git a/source/java/org/alfresco/web/bean/rules/handlers/PropertyValueHandler.java b/source/java/org/alfresco/web/bean/rules/handlers/PropertyValueHandler.java index 5c68841bc9..ab9b09ca06 100644 --- a/source/java/org/alfresco/web/bean/rules/handlers/PropertyValueHandler.java +++ b/source/java/org/alfresco/web/bean/rules/handlers/PropertyValueHandler.java @@ -18,7 +18,7 @@ * 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 + * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ @@ -52,6 +52,12 @@ public class PropertyValueHandler extends BaseConditionHandler public void prepareForSave(Map conditionProps, Map repoProps) + { + prepareForSaveWithCorrectType(conditionProps, repoProps); + } + + //Responsible for serializing the value of the property, which could have different types + protected void prepareForSaveWithCorrectType(Map conditionProps, Map repoProps) { String text = (String)conditionProps.get(PROP_CONTAINS_TEXT); repoProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, text); @@ -59,11 +65,18 @@ public class PropertyValueHandler extends BaseConditionHandler public void prepareForEdit(Map conditionProps, Map repoProps) + { + prepareForEditWithCorrectType(conditionProps, repoProps); + } + + protected void prepareForEditWithCorrectType(Map conditionProps, + Map repoProps) { String propValue = (String)repoProps.get(ComparePropertyValueEvaluator.PARAM_VALUE); conditionProps.put(PROP_CONTAINS_TEXT, propValue); } + public String generateSummary(FacesContext context, IWizardBean wizard, Map conditionProps) { diff --git a/source/java/org/alfresco/web/bean/rules/handlers/property/DatePropertyValueConditionHandler.java b/source/java/org/alfresco/web/bean/rules/handlers/property/DatePropertyValueConditionHandler.java new file mode 100644 index 0000000000..5c9eb72152 --- /dev/null +++ b/source/java/org/alfresco/web/bean/rules/handlers/property/DatePropertyValueConditionHandler.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2005-2008 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 received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.bean.rules.handlers.property; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator; +import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation; + +/** + * Condition handler for the "compare-date-property" condition. + * + * @author Jean Barmash + */ +public class DatePropertyValueConditionHandler extends TextPropertyValueConditionHandler +{ + + public static final String NAME = "compare-date-property"; + + @Override + protected String getConditionName() + { + return DatePropertyValueConditionHandler.NAME; + } + + //Responsible for serializing the value of the property, which could have different types + protected void prepareForSaveWithCorrectType(Map conditionProps, Map repoProps) + { + Date date = (Date) conditionProps.get(PROP_CONTAINS_TEXT); + repoProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, date); + } + + protected void prepareForEditWithCorrectType(Map conditionProps, + Map repoProps) + { + Date dateValue = (Date) repoProps.get(ComparePropertyValueEvaluator.PARAM_VALUE); + conditionProps.put(PROP_CONTAINS_TEXT, dateValue); + } + + @Override + protected String getSummaryStringTemplate(Boolean not) + { + String msgId = not.booleanValue() ? "condition_compare_date_property_value_not" + : "condition_compare_date_property_value"; + return msgId; + } + + @Override + protected String displayOperation(String operation) + { + ComparePropertyValueOperation op = ComparePropertyValueOperation.valueOf(operation); + switch (op) + { + case EQUALS: + return "property_date_condition_equals"; + case GREATER_THAN: + return "property_date_condition_greaterthan"; + case GREATER_THAN_EQUAL: + return "property_date_condition_greaterthanequals"; + case LESS_THAN: + return "property_date_condition_lessthan"; + case LESS_THAN_EQUAL: + return "property_date_condition_lessthanequals"; + default: return "property_condition_invalid"; + } + } + + +} diff --git a/source/java/org/alfresco/web/bean/rules/handlers/property/IntegerPropertyValueConditionHandler.java b/source/java/org/alfresco/web/bean/rules/handlers/property/IntegerPropertyValueConditionHandler.java new file mode 100644 index 0000000000..0380577f27 --- /dev/null +++ b/source/java/org/alfresco/web/bean/rules/handlers/property/IntegerPropertyValueConditionHandler.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2005-2008 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 received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.bean.rules.handlers.property; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator; +import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation; + +/** + * Condition handler for the "compare-integer-property" condition. + * + * @author Jean Barmash + */ +public class IntegerPropertyValueConditionHandler extends TextPropertyValueConditionHandler +{ + + public static final String NAME = "compare-integer-property"; + + @Override + protected String getConditionName() + { + return IntegerPropertyValueConditionHandler.NAME; + } + + //Responsible for serializing the value of the property, which could have different types + protected void prepareForSaveWithCorrectType(Map conditionProps, Map repoProps) + { + Long number = Long.parseLong((String)conditionProps.get(PROP_CONTAINS_TEXT)); + repoProps.put(ComparePropertyValueEvaluator.PARAM_VALUE, number ); + } + + protected void prepareForEditWithCorrectType(Map conditionProps, + Map repoProps) + { + Long propValue = (Long)repoProps.get(ComparePropertyValueEvaluator.PARAM_VALUE); + conditionProps.put(PROP_CONTAINS_TEXT, propValue.toString()); + } + + @Override + protected String getSummaryStringTemplate(Boolean not) + { + String msgId = not.booleanValue() ? "condition_compare_integer_property_value_not" + : "condition_compare_integer_property_value"; + return msgId; + } + + @Override + protected String displayOperation(String operation) + { + ComparePropertyValueOperation op = ComparePropertyValueOperation.valueOf(operation); + switch (op) + { + case EQUALS: + return "property_condition_equals"; + case GREATER_THAN: + return "property_condition_greaterthan"; + case GREATER_THAN_EQUAL: + return "property_condition_greaterthanequals"; + case LESS_THAN: + return "property_condition_lessthan"; + case LESS_THAN_EQUAL: + return "property_condition_lessthanequals"; + default: return "property_condition_invalid"; + } + } + + +} diff --git a/source/java/org/alfresco/web/bean/rules/handlers/property/TextPropertyValueConditionHandler.java b/source/java/org/alfresco/web/bean/rules/handlers/property/TextPropertyValueConditionHandler.java new file mode 100644 index 0000000000..b8aeb81b5c --- /dev/null +++ b/source/java/org/alfresco/web/bean/rules/handlers/property/TextPropertyValueConditionHandler.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2005-2008 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 received a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.bean.rules.handlers.property; + +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.Map; + +import javax.faces.context.FacesContext; + +import org.alfresco.repo.action.evaluator.ComparePropertyValueEvaluator; +import org.alfresco.repo.action.evaluator.compare.ComparePropertyValueOperation; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.rules.handlers.PropertyValueHandler; +import org.alfresco.web.bean.wizard.IWizardBean; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Condition handler for the "compare-text-property" condition. + * + * @author Jean Barmash + */ +public class TextPropertyValueConditionHandler extends PropertyValueHandler +{ + private static final Log logger = LogFactory.getLog(TextPropertyValueConditionHandler.class); + public static final String NAME = "compare-text-property"; + + public static final String UI_PARAM_OPERATION = "operation"; + public static final String UI_PARAM_QNAME = "qname"; + + public String getJSPPath() + { + return getJSPPath(getConditionName()); + } + + protected String getConditionName() + { + return TextPropertyValueConditionHandler.NAME; + } + + public void prepareForSave(Map conditionParams, Map repoProps) + { + if (logger.isDebugEnabled()) + logger.debug("Preparing to Save Text Condition Parameters"); + + super.prepareForSave(conditionParams, repoProps); + String propertyString = (String) conditionParams.get(UI_PARAM_QNAME); + + FacesContext fc = FacesContext.getCurrentInstance(); + ServiceRegistry serviceRegistry = Repository.getServiceRegistry(fc); + QName qname = null; + + if ((propertyString.indexOf(':')) == -1) // TODO: there might be a better way to resolve namespaces + qname = QName.createQName(propertyString); + else + qname = QName.createQName(propertyString, serviceRegistry.getNamespaceService()); + + if (logger.isDebugEnabled()) + logger.warn("Storing Property QName " + qname); + + repoProps.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, qname); + + String operation = (String) conditionParams.get(UI_PARAM_OPERATION); + repoProps.put(ComparePropertyValueEvaluator.PARAM_OPERATION, operation); + } + + public void prepareForEdit(Map conditionProps, Map repoProps) + { + if (logger.isDebugEnabled()) + logger.debug("Retrieving Text Condition Parameters for editing"); + + super.prepareForEdit(conditionProps, repoProps); + conditionProps.put(UI_PARAM_QNAME, ((QName) repoProps.get(ComparePropertyValueEvaluator.PARAM_PROPERTY)) + .toPrefixString()); + conditionProps.put(UI_PARAM_OPERATION, repoProps.get(ComparePropertyValueEvaluator.PARAM_OPERATION).toString()); + } + + public String generateSummary(FacesContext context, IWizardBean wizard, Map conditionProps) + { + Boolean not = (Boolean) conditionProps.get(PROP_CONDITION_NOT); + String msgId = getSummaryStringTemplate(not); + String text = conditionProps.get(PROP_CONTAINS_TEXT).toString(); + String operation = (String) conditionProps.get(UI_PARAM_OPERATION); + String qname = (String) conditionProps.get(UI_PARAM_QNAME); + + return MessageFormat.format(Application.getMessage(context, msgId), new Object[] + { qname, Application.getMessage(context, displayOperation(operation)), text }); + } + + protected String displayOperation(String operation) + { + ComparePropertyValueOperation op = ComparePropertyValueOperation.valueOf(operation); + switch (op) + { + case EQUALS: + return "property_date_condition_equals"; + case CONTAINS: + return "property_condition_contains"; + case BEGINS: + return "property_condition_beginswith"; + case ENDS: + return "property_condition_endswith"; + default: return "property_condition_invalid"; + } + } + + protected String getSummaryStringTemplate(Boolean not) + { + String msgId = not.booleanValue() ? "condition_compare_text_property_value_not" + : "condition_compare_text_property_value"; + return msgId; + } + +} diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index e7029dc43e..d359b425ac 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -518,6 +518,11 @@ ClipboardBean org.alfresco.web.bean.clipboard.ClipboardBean session + + + nodeService + #{NodeService} + @@ -995,7 +1000,7 @@ The bean that backs up the Create Rule Wizard CreateRuleWizard - org.alfresco.web.bean.rules.CreateRuleWizard + org.alfresco.web.bean.rules.CreateCompositeRuleWizard session nodeService diff --git a/source/web/jsp/actions/mail.jsp b/source/web/jsp/actions/mail.jsp index 78f5cf0dc9..087daadf51 100644 --- a/source/web/jsp/actions/mail.jsp +++ b/source/web/jsp/actions/mail.jsp @@ -47,19 +47,23 @@ function checkButtonState() { - if (document.getElementById("email-action:subject").value.length == 0) + var disableBtn = document.getElementById("finishButtonDisabled").innerHTML; + if (document.getElementById("email-action:subject").value.length > 0 && disableBtn == "false") { - document.getElementById("email-action:ok-button").disabled = true; + document.getElementById("email-action:ok-button").disabled = false; } else { - document.getElementById("email-action:ok-button").disabled = false; + document.getElementById("email-action:ok-button").disabled = true; } } +