/******************************************************************************* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* 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.ofbiz.widget.model; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.ListIterator; | |
import java.util.Map; | |
import java.util.regex.PatternSyntaxException; | |
import org.ofbiz.base.util.Debug; | |
import org.ofbiz.base.util.UtilGenerics; | |
import org.ofbiz.base.util.UtilValidate; | |
import org.ofbiz.base.util.UtilXml; | |
import org.ofbiz.base.util.collections.FlexibleMapAccessor; | |
import org.ofbiz.base.util.string.FlexibleStringExpander; | |
import org.ofbiz.entity.finder.EntityFinderUtil; | |
import org.ofbiz.service.GenericServiceException; | |
import org.ofbiz.service.ModelService; | |
import org.ofbiz.widget.WidgetWorker; | |
import org.w3c.dom.Element; | |
/** | |
* Abstract form action. | |
*/ | |
public abstract class ModelFormAction { | |
public static final String module = ModelFormAction.class.getName(); | |
public static List<ModelAction> readSubActions(ModelForm modelForm, Element parentElement) { | |
List<? extends Element> actionElementList = UtilXml.childElementList(parentElement); | |
List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size()); | |
for (Element actionElement : UtilXml.childElementList(parentElement)) { | |
if ("service".equals(actionElement.getNodeName())) { | |
actions.add(new Service(modelForm, actionElement)); | |
} else if ("entity-and".equals(actionElement.getNodeName()) || "entity-condition".equals(actionElement.getNodeName()) | |
|| "get-related".equals(actionElement.getNodeName())) { | |
if (!actionElement.hasAttribute("list")) { | |
String listName = modelForm.getListName(); | |
if (UtilValidate.isEmpty(listName)) { | |
listName = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME; | |
} | |
actionElement.setAttribute("list", listName); | |
} | |
actions.add(AbstractModelAction.newInstance(modelForm, actionElement)); | |
} else if ("call-parent-actions".equals(actionElement.getNodeName())) { | |
actions.add(new CallParentActions(modelForm, actionElement)); | |
} else { | |
actions.add(AbstractModelAction.newInstance(modelForm, actionElement)); | |
} | |
} | |
return Collections.unmodifiableList(actions); | |
} | |
/** | |
* Models the <call-parent-actions> element. | |
* | |
* @see <code>widget-form.xsd</code> | |
*/ | |
@SuppressWarnings("serial") | |
public static class CallParentActions extends AbstractModelAction { | |
private final ActionsKind kind;; | |
private final ModelForm modelForm; | |
public CallParentActions(ModelForm modelForm, Element callParentActionsElement) { | |
super(modelForm, callParentActionsElement); | |
String parentName = callParentActionsElement.getParentNode().getNodeName(); | |
if ("actions".equals(parentName)) { | |
kind = ActionsKind.ACTIONS; | |
} else if ("row-actions".equals(parentName)) { | |
kind = ActionsKind.ROW_ACTIONS; | |
} else { | |
throw new IllegalArgumentException("Action element not supported for call-parent-actions : " + parentName); | |
} | |
ModelForm parentModel = modelForm.getParentModelForm(); | |
if (parentModel == null) { | |
throw new IllegalArgumentException("call-parent-actions can only be used with form extending another form"); | |
} | |
this.modelForm = modelForm; | |
} | |
@Override | |
public void accept(ModelActionVisitor visitor) throws Exception { | |
visitor.visit(this); | |
} | |
@Override | |
public void runAction(Map<String, Object> context) { | |
ModelForm parentModel = modelForm.getParentModelForm(); | |
switch (kind) { | |
case ACTIONS: | |
parentModel.runFormActions(context); | |
break; | |
case ROW_ACTIONS: | |
AbstractModelAction.runSubActions(parentModel.getRowActions(), context); | |
break; | |
} | |
} | |
protected static enum ActionsKind { | |
ACTIONS, ROW_ACTIONS | |
} | |
} | |
/** | |
* Models the <service> element. | |
* | |
* @see <code>widget-form.xsd</code> | |
*/ | |
@SuppressWarnings("serial") | |
public static class Service extends AbstractModelAction { | |
private final FlexibleStringExpander autoFieldMapExdr; | |
private final Map<FlexibleMapAccessor<Object>, Object> fieldMap; | |
private final boolean ignoreError; | |
private final FlexibleStringExpander resultMapListNameExdr; | |
private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr; | |
private final FlexibleStringExpander serviceNameExdr; | |
public Service(ModelForm modelForm, Element serviceElement) { | |
super(modelForm, serviceElement); | |
this.serviceNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("service-name")); | |
this.resultMapNameAcsr = FlexibleMapAccessor.getInstance(serviceElement.getAttribute("result-map")); | |
this.autoFieldMapExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("auto-field-map")); | |
FlexibleStringExpander resultMapListNameExdr = FlexibleStringExpander.getInstance(""); | |
if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list")) | |
&& UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-name"))) { | |
if (UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator")) | |
&& UtilValidate.isEmpty(serviceElement.getAttribute("result-map-list-iterator-name"))) { | |
String lstNm = modelForm.getListName(); | |
if (UtilValidate.isEmpty(lstNm)) { | |
lstNm = ModelForm.DEFAULT_FORM_RESULT_LIST_NAME; | |
} | |
resultMapListNameExdr = FlexibleStringExpander.getInstance(lstNm); | |
} else { | |
// this is deprecated, but support it for now anyway | |
resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement | |
.getAttribute("result-map-list-iterator")); | |
if (resultMapListNameExdr.isEmpty()) | |
resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement | |
.getAttribute("result-map-list-iterator-name")); | |
} | |
} else { | |
resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement.getAttribute("result-map-list")); | |
if (resultMapListNameExdr.isEmpty()) | |
resultMapListNameExdr = FlexibleStringExpander.getInstance(serviceElement | |
.getAttribute("result-map-list-name")); | |
} | |
this.resultMapListNameExdr = resultMapListNameExdr; | |
this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement); | |
this.ignoreError = "true".equals(serviceElement.getAttribute("ignore-error")); | |
} | |
@Override | |
public void accept(ModelActionVisitor visitor) throws Exception { | |
visitor.visit(this); | |
} | |
public String getServiceName() { | |
return serviceNameExdr.getOriginal(); | |
} | |
@Override | |
public void runAction(Map<String, Object> context) { | |
String serviceNameExpanded = this.serviceNameExdr.expandString(context); | |
if (UtilValidate.isEmpty(serviceNameExpanded)) { | |
throw new IllegalArgumentException("Service name was empty, expanded from: " + this.serviceNameExdr.getOriginal()); | |
} | |
String autoFieldMapString = this.autoFieldMapExdr.expandString(context); | |
boolean autoFieldMapBool = !"false".equals(autoFieldMapString); | |
try { | |
Map<String, Object> serviceContext = null; | |
if (autoFieldMapBool) { | |
if (!"true".equals(autoFieldMapString)) { | |
Map<String, Object> autoFieldMap = UtilGenerics.checkMap(context.get(autoFieldMapString)); | |
serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext() | |
.makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, autoFieldMap); | |
} else { | |
serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext() | |
.makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, context); | |
} | |
} else { | |
serviceContext = new HashMap<String, Object>(); | |
} | |
if (this.fieldMap != null) { | |
EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext); | |
} | |
Map<String, Object> result = null; | |
if (this.ignoreError) { | |
result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext, -1, true); | |
} else { | |
result = WidgetWorker.getDispatcher(context).runSync(serviceNameExpanded, serviceContext); | |
} | |
if (!this.resultMapNameAcsr.isEmpty()) { | |
this.resultMapNameAcsr.put(context, result); | |
String queryString = (String) result.get("queryString"); | |
context.put("queryString", queryString); | |
context.put("queryStringMap", result.get("queryStringMap")); | |
if (UtilValidate.isNotEmpty(queryString)) { | |
try { | |
String queryStringEncoded = queryString.replaceAll("&", "%26"); | |
context.put("queryStringEncoded", queryStringEncoded); | |
} catch (PatternSyntaxException e) { | |
} | |
} | |
} else { | |
context.putAll(result); | |
} | |
String listName = resultMapListNameExdr.expandString(context); | |
Object listObj = result.get(listName); | |
if (listObj != null) { | |
if (!(listObj instanceof List<?>) && !(listObj instanceof ListIterator<?>)) { | |
throw new IllegalArgumentException("Error in form [" + this.getModelWidget().getName() | |
+ "] calling service with name [" + serviceNameExpanded | |
+ "]: the result that is supposed to be a List or ListIterator and is not."); | |
} | |
context.put("listName", listName); | |
context.put(listName, listObj); | |
} | |
} catch (GenericServiceException e) { | |
String errMsg = "Error in form [" + this.getModelWidget().getName() + "] calling service with name [" | |
+ serviceNameExpanded + "]: " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
if (!this.ignoreError) { | |
throw new IllegalArgumentException(errMsg); | |
} | |
} | |
} | |
public FlexibleStringExpander getAutoFieldMapExdr() { | |
return autoFieldMapExdr; | |
} | |
public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() { | |
return fieldMap; | |
} | |
public boolean getIgnoreError() { | |
return ignoreError; | |
} | |
public FlexibleStringExpander getResultMapListNameExdr() { | |
return resultMapListNameExdr; | |
} | |
public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() { | |
return resultMapNameAcsr; | |
} | |
public FlexibleStringExpander getServiceNameExdr() { | |
return serviceNameExdr; | |
} | |
} | |
} |