| /******************************************************************************* |
| * 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.apache.ofbiz.widget.model; |
| |
| import java.io.Serializable; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.TimeZone; |
| import java.util.regex.PatternSyntaxException; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.http.HttpSession; |
| |
| import org.apache.ofbiz.base.util.Debug; |
| import org.apache.ofbiz.base.util.GeneralException; |
| import org.apache.ofbiz.base.util.ObjectType; |
| import org.apache.ofbiz.base.util.ScriptUtil; |
| import org.apache.ofbiz.base.util.StringUtil; |
| import org.apache.ofbiz.base.util.UtilGenerics; |
| import org.apache.ofbiz.base.util.UtilProperties; |
| import org.apache.ofbiz.base.util.UtilValidate; |
| import org.apache.ofbiz.base.util.UtilXml; |
| import org.apache.ofbiz.base.util.collections.FlexibleMapAccessor; |
| import org.apache.ofbiz.base.util.collections.ResourceBundleMapWrapper; |
| import org.apache.ofbiz.base.util.string.FlexibleStringExpander; |
| import org.apache.ofbiz.entity.GenericEntityException; |
| import org.apache.ofbiz.entity.GenericValue; |
| import org.apache.ofbiz.entity.finder.ByAndFinder; |
| import org.apache.ofbiz.entity.finder.ByConditionFinder; |
| import org.apache.ofbiz.entity.finder.EntityFinderUtil; |
| import org.apache.ofbiz.entity.finder.PrimaryKeyFinder; |
| import org.apache.ofbiz.entity.util.EntityUtilProperties; |
| import org.apache.ofbiz.minilang.MiniLangException; |
| import org.apache.ofbiz.minilang.SimpleMethod; |
| import org.apache.ofbiz.minilang.method.MethodContext; |
| import org.apache.ofbiz.service.DispatchContext; |
| import org.apache.ofbiz.service.GenericServiceException; |
| import org.apache.ofbiz.service.ModelService; |
| import org.apache.ofbiz.widget.WidgetWorker; |
| import org.w3c.dom.Element; |
| |
| /** |
| * Abstract base class for the action models. |
| */ |
| @SuppressWarnings("serial") |
| public abstract class AbstractModelAction implements Serializable, ModelAction { |
| |
| /* |
| * ----------------------------------------------------------------------- * |
| * DEVELOPERS PLEASE READ |
| * ----------------------------------------------------------------------- * |
| * |
| * This model is intended to be a read-only data structure that represents |
| * an XML element. Outside of object construction, the class should not |
| * have any behaviors. |
| * |
| * Instances of this class will be shared by multiple threads - therefore |
| * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME! |
| * |
| */ |
| |
| public static final String module = AbstractModelAction.class.getName(); |
| |
| /** |
| * Returns a new <code>ModelAction</code> instance, built from <code>actionElement</code>. |
| * |
| * @param modelWidget The <code>ModelWidget</code> that contains the <actions> element |
| * @param actionElement |
| * @return A new <code>ModelAction</code> instance |
| */ |
| public static ModelAction newInstance(ModelWidget modelWidget, Element actionElement) { |
| String nodeName = UtilXml.getNodeNameIgnorePrefix(actionElement); |
| if ("set".equals(nodeName)) { |
| return new SetField(modelWidget, actionElement); |
| } else if ("property-map".equals(nodeName)) { |
| return new PropertyMap(modelWidget, actionElement); |
| } else if ("property-to-field".equals(nodeName)) { |
| return new PropertyToField(modelWidget, actionElement); |
| } else if ("script".equals(nodeName)) { |
| return new Script(modelWidget, actionElement); |
| } else if ("service".equals(nodeName)) { |
| return new Service(modelWidget, actionElement); |
| } else if ("entity-one".equals(nodeName)) { |
| return new EntityOne(modelWidget, actionElement); |
| } else if ("entity-and".equals(nodeName)) { |
| return new EntityAnd(modelWidget, actionElement); |
| } else if ("entity-condition".equals(nodeName)) { |
| return new EntityCondition(modelWidget, actionElement); |
| } else if ("get-related-one".equals(nodeName)) { |
| return new GetRelatedOne(modelWidget, actionElement); |
| } else if ("get-related".equals(nodeName)) { |
| return new GetRelated(modelWidget, actionElement); |
| } else { |
| throw new IllegalArgumentException("Action element not supported with name: " + actionElement.getNodeName()); |
| } |
| } |
| |
| public static List<ModelAction> readSubActions(ModelWidget modelWidget, Element parentElement) { |
| List<? extends Element> actionElementList = UtilXml.childElementList(parentElement); |
| List<ModelAction> actions = new ArrayList<ModelAction>(actionElementList.size()); |
| for (Element actionElement : actionElementList) { |
| actions.add(newInstance(modelWidget, actionElement)); |
| } |
| return Collections.unmodifiableList(actions); |
| } |
| |
| /** |
| * Executes the actions contained in <code>actions</code>. |
| * |
| * @param actions |
| * @param context |
| */ |
| public static void runSubActions(List<ModelAction> actions, Map<String, Object> context) { |
| if (actions == null) |
| return; |
| for (ModelAction action : actions) { |
| if (Debug.verboseOn()) |
| Debug.logVerbose("Running action " + action.getClass().getName(), module); |
| try { |
| action.runAction(context); |
| } catch (GeneralException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
| |
| private final ModelWidget modelWidget; |
| |
| protected AbstractModelAction() { |
| // FIXME: This should not be null. |
| this.modelWidget = null; |
| } |
| |
| protected AbstractModelAction(ModelWidget modelWidget, Element actionElement) { |
| this.modelWidget = modelWidget; |
| if (Debug.verboseOn()) |
| Debug.logVerbose("Reading widget action with name: " + actionElement.getNodeName(), module); |
| } |
| |
| /** |
| * Returns the <code>ModelWidget</code> that contains the <actions> element. |
| * |
| * @return The <code>ModelWidget</code> that contains the <actions> element |
| */ |
| public ModelWidget getModelWidget() { |
| return modelWidget; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| ModelActionVisitor visitor = new XmlWidgetActionVisitor(sb); |
| try { |
| accept(visitor); |
| } catch (Exception e) { |
| Debug.logWarning(e, "Exception thrown in XmlWidgetActionVisitor: ", module); |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Models the <entity-and> element. |
| * |
| * @see <code>widget-screen.xsd</code> |
| */ |
| public static class EntityAnd extends AbstractModelAction { |
| private final ByAndFinder finder; |
| |
| public EntityAnd(ModelWidget modelWidget, Element entityAndElement) { |
| super(modelWidget, entityAndElement); |
| finder = new ByAndFinder(entityAndElement); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public ByAndFinder getFinder() { |
| return this.finder; |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| try { |
| finder.runFind(context, WidgetWorker.getDelegator(context)); |
| } catch (GeneralException e) { |
| String errMsg = "Error doing entity query by condition: " + e.toString(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| } |
| |
| /** |
| * Models the <entity-condition> element. |
| * |
| * @see <code>widget-screen.xsd</code> |
| */ |
| public static class EntityCondition extends AbstractModelAction { |
| private final ByConditionFinder finder; |
| |
| public EntityCondition(ModelWidget modelWidget, Element entityConditionElement) { |
| super(modelWidget, entityConditionElement); |
| finder = new ByConditionFinder(entityConditionElement); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public ByConditionFinder getFinder() { |
| return this.finder; |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| try { |
| finder.runFind(context, WidgetWorker.getDelegator(context)); |
| } catch (GeneralException e) { |
| String errMsg = "Error doing entity query by condition: " + e.toString(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| } |
| |
| /** |
| * Models the <entity-one> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class EntityOne extends AbstractModelAction { |
| private final PrimaryKeyFinder finder; |
| |
| public EntityOne(ModelWidget modelWidget, Element entityOneElement) { |
| super(modelWidget, entityOneElement); |
| finder = new PrimaryKeyFinder(entityOneElement); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public PrimaryKeyFinder getFinder() { |
| return this.finder; |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| try { |
| finder.runFind(context, WidgetWorker.getDelegator(context)); |
| } catch (GeneralException e) { |
| String errMsg = "Error doing entity query by condition: " + e.toString(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| } |
| |
| /** |
| * Models the <get-related> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class GetRelated extends AbstractModelAction { |
| private final FlexibleMapAccessor<List<GenericValue>> listNameAcsr; |
| private final FlexibleMapAccessor<Map<String, Object>> mapAcsr; |
| private final FlexibleMapAccessor<List<String>> orderByListAcsr; |
| private final String relationName; |
| private final boolean useCache; |
| private final FlexibleMapAccessor<Object> valueNameAcsr; |
| |
| public GetRelated(ModelWidget modelWidget, Element getRelatedElement) { |
| super(modelWidget, getRelatedElement); |
| this.valueNameAcsr = FlexibleMapAccessor.getInstance(getRelatedElement.getAttribute("value-field")); |
| this.listNameAcsr = FlexibleMapAccessor.getInstance(getRelatedElement.getAttribute("list")); |
| this.relationName = getRelatedElement.getAttribute("relation-name"); |
| this.mapAcsr = FlexibleMapAccessor.getInstance(getRelatedElement.getAttribute("map")); |
| this.orderByListAcsr = FlexibleMapAccessor.getInstance(getRelatedElement.getAttribute("order-by-list")); |
| this.useCache = "true".equals(getRelatedElement.getAttribute("use-cache")); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public String getRelationName() { |
| return this.relationName; |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| Object valueObject = valueNameAcsr.get(context); |
| if (valueObject == null) { |
| Debug.logVerbose("Value not found with name: " + valueNameAcsr + ", not getting related...", module); |
| return; |
| } |
| if (!(valueObject instanceof GenericValue)) { |
| String errMsg = "Env variable for value-name " + valueNameAcsr.toString() |
| + " is not a GenericValue object; for the relation-name: " + relationName + "]"; |
| Debug.logError(errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| GenericValue value = (GenericValue) valueObject; |
| List<String> orderByNames = null; |
| if (!orderByListAcsr.isEmpty()) { |
| orderByNames = orderByListAcsr.get(context); |
| } |
| Map<String, Object> constraintMap = null; |
| if (!mapAcsr.isEmpty()) { |
| constraintMap = mapAcsr.get(context); |
| } |
| try { |
| listNameAcsr.put(context, value.getRelated(relationName, constraintMap, orderByNames, useCache)); |
| } catch (GenericEntityException e) { |
| String errMsg = "Problem getting related from entity with name " + value.getEntityName() |
| + " for the relation-name: " + relationName + ": " + e.getMessage(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| |
| public FlexibleMapAccessor<List<GenericValue>> getListNameAcsr() { |
| return listNameAcsr; |
| } |
| |
| public FlexibleMapAccessor<Map<String, Object>> getMapAcsr() { |
| return mapAcsr; |
| } |
| |
| public FlexibleMapAccessor<List<String>> getOrderByListAcsr() { |
| return orderByListAcsr; |
| } |
| |
| public boolean getUseCache() { |
| return useCache; |
| } |
| |
| public FlexibleMapAccessor<Object> getValueNameAcsr() { |
| return valueNameAcsr; |
| } |
| } |
| |
| /** |
| * Models the <get-related-one> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class GetRelatedOne extends AbstractModelAction { |
| private final String relationName; |
| private final FlexibleMapAccessor<Object> toValueNameAcsr; |
| private final boolean useCache; |
| private final FlexibleMapAccessor<Object> valueNameAcsr; |
| |
| public GetRelatedOne(ModelWidget modelWidget, Element getRelatedOneElement) { |
| super(modelWidget, getRelatedOneElement); |
| this.valueNameAcsr = FlexibleMapAccessor.getInstance(getRelatedOneElement.getAttribute("value-field")); |
| this.toValueNameAcsr = FlexibleMapAccessor.getInstance(getRelatedOneElement.getAttribute("to-value-field")); |
| this.relationName = getRelatedOneElement.getAttribute("relation-name"); |
| this.useCache = "true".equals(getRelatedOneElement.getAttribute("use-cache")); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public String getRelationName() { |
| return this.relationName; |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| Object valueObject = valueNameAcsr.get(context); |
| if (valueObject == null) { |
| Debug.logVerbose("Value not found with name: " + valueNameAcsr + ", not getting related...", module); |
| return; |
| } |
| if (!(valueObject instanceof GenericValue)) { |
| String errMsg = "Env variable for value-name " + valueNameAcsr.toString() |
| + " is not a GenericValue object; for the relation-name: " + relationName + "]"; |
| Debug.logError(errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| GenericValue value = (GenericValue) valueObject; |
| try { |
| toValueNameAcsr.put(context, value.getRelatedOne(relationName, useCache)); |
| } catch (GenericEntityException e) { |
| String errMsg = "Problem getting related one from entity with name " + value.getEntityName() |
| + " for the relation-name: " + relationName + ": " + e.getMessage(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| |
| public FlexibleMapAccessor<Object> getToValueNameAcsr() { |
| return toValueNameAcsr; |
| } |
| |
| public boolean getUseCache() { |
| return useCache; |
| } |
| |
| public FlexibleMapAccessor<Object> getValueNameAcsr() { |
| return valueNameAcsr; |
| } |
| } |
| |
| /** |
| * Models the <property-map> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class PropertyMap extends AbstractModelAction { |
| private final FlexibleStringExpander globalExdr; |
| private final FlexibleMapAccessor<ResourceBundleMapWrapper> mapNameAcsr; |
| private final FlexibleStringExpander resourceExdr; |
| |
| public PropertyMap(ModelWidget modelWidget, Element setElement) { |
| super(modelWidget, setElement); |
| this.resourceExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("resource")); |
| this.mapNameAcsr = FlexibleMapAccessor.getInstance(setElement.getAttribute("map-name")); |
| this.globalExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("global")); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| String globalStr = this.globalExdr.expandString(context); |
| // default to false |
| boolean global = "true".equals(globalStr); |
| Locale locale = (Locale) context.get("locale"); |
| String resource = this.resourceExdr.expandString(context, locale); |
| ResourceBundleMapWrapper existingPropMap = this.mapNameAcsr.get(context); |
| if (existingPropMap == null) { |
| this.mapNameAcsr.put(context, UtilProperties.getResourceBundleMap(resource, locale, context)); |
| } else { |
| try { |
| existingPropMap.addBottomResourceBundle(resource); |
| } catch (IllegalArgumentException e) { |
| // log the error, but don't let it kill everything just for a typo or bad char in an l10n file |
| Debug.logError(e, "Error adding resource bundle [" + resource + "]: " + e.toString(), module); |
| } |
| } |
| if (global) { |
| Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext")); |
| if (globalCtx != null) { |
| ResourceBundleMapWrapper globalExistingPropMap = this.mapNameAcsr.get(globalCtx); |
| if (globalExistingPropMap == null) { |
| this.mapNameAcsr.put(globalCtx, UtilProperties.getResourceBundleMap(resource, locale, context)); |
| } else { |
| // is it the same object? if not add it in here too... |
| if (existingPropMap != globalExistingPropMap) { |
| try { |
| globalExistingPropMap.addBottomResourceBundle(resource); |
| } catch (IllegalArgumentException e) { |
| // log the error, but don't let it kill everything just for a typo or bad char in an l10n file |
| Debug.logError(e, "Error adding resource bundle [" + resource + "]: " + e.toString(), module); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| public FlexibleStringExpander getGlobalExdr() { |
| return globalExdr; |
| } |
| |
| public FlexibleMapAccessor<ResourceBundleMapWrapper> getMapNameAcsr() { |
| return mapNameAcsr; |
| } |
| |
| public FlexibleStringExpander getResourceExdr() { |
| return resourceExdr; |
| } |
| } |
| |
| /** |
| * Models the <property-to-field> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class PropertyToField extends AbstractModelAction { |
| private final FlexibleMapAccessor<List<? extends Object>> argListAcsr; |
| private final FlexibleStringExpander defaultExdr; |
| private final FlexibleMapAccessor<Object> fieldAcsr; |
| private final FlexibleStringExpander globalExdr; |
| private final boolean noLocale; |
| private final FlexibleStringExpander propertyExdr; |
| private final FlexibleStringExpander resourceExdr; |
| |
| public PropertyToField(ModelWidget modelWidget, Element setElement) { |
| super(modelWidget, setElement); |
| this.resourceExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("resource")); |
| this.propertyExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("property")); |
| this.fieldAcsr = FlexibleMapAccessor.getInstance(setElement.getAttribute("field")); |
| this.defaultExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("default")); |
| this.noLocale = "true".equals(setElement.getAttribute("no-locale")); |
| this.argListAcsr = FlexibleMapAccessor.getInstance(setElement.getAttribute("arg-list-name")); |
| this.globalExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("global")); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) { |
| //String globalStr = this.globalExdr.expandString(context); |
| // default to false |
| //boolean global = "true".equals(globalStr); |
| Locale locale = (Locale) context.get("locale"); |
| String resource = this.resourceExdr.expandString(context, locale); |
| String property = this.propertyExdr.expandString(context, locale); |
| String value = null; |
| if (noLocale) { |
| value = EntityUtilProperties.getPropertyValue(resource, property, WidgetWorker.getDelegator(context)); |
| } else { |
| value = EntityUtilProperties.getMessage(resource, property, locale, WidgetWorker.getDelegator(context)); |
| } |
| if (UtilValidate.isEmpty(value)) { |
| value = this.defaultExdr.expandString(context); |
| } |
| // note that expanding the value string here will handle defaultValue and the string from |
| // the properties file; if we decide later that we don't want the string from the properties |
| // file to be expanded we should just expand the defaultValue at the beginning of this method. |
| value = FlexibleStringExpander.expandString(value, context); |
| if (!argListAcsr.isEmpty()) { |
| List<? extends Object> argList = argListAcsr.get(context); |
| if (UtilValidate.isNotEmpty(argList)) { |
| value = MessageFormat.format(value, argList.toArray()); |
| } |
| } |
| fieldAcsr.put(context, value); |
| } |
| |
| public FlexibleMapAccessor<List<? extends Object>> getArgListAcsr() { |
| return argListAcsr; |
| } |
| |
| public FlexibleStringExpander getDefaultExdr() { |
| return defaultExdr; |
| } |
| |
| public FlexibleMapAccessor<Object> getFieldAcsr() { |
| return fieldAcsr; |
| } |
| |
| public FlexibleStringExpander getGlobalExdr() { |
| return globalExdr; |
| } |
| |
| public boolean getNoLocale() { |
| return noLocale; |
| } |
| |
| public FlexibleStringExpander getPropertyExdr() { |
| return propertyExdr; |
| } |
| |
| public FlexibleStringExpander getResourceExdr() { |
| return resourceExdr; |
| } |
| } |
| |
| /** |
| * Models the <script> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class Script extends AbstractModelAction { |
| private final String location; |
| private final String method; |
| |
| public Script(ModelWidget modelWidget, Element scriptElement) { |
| super(modelWidget, scriptElement); |
| String scriptLocation = scriptElement.getAttribute("location"); |
| this.location = WidgetWorker.getScriptLocation(scriptLocation); |
| this.method = WidgetWorker.getScriptMethodName(scriptLocation); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| @Override |
| public void runAction(Map<String, Object> context) throws GeneralException { |
| if (location.endsWith(".xml")) { |
| Map<String, Object> localContext = new HashMap<String, Object>(); |
| localContext.putAll(context); |
| DispatchContext ctx = WidgetWorker.getDispatcher(context).getDispatchContext(); |
| MethodContext methodContext = new MethodContext(ctx, localContext, null); |
| try { |
| SimpleMethod.runSimpleMethod(location, method, methodContext); |
| context.putAll(methodContext.getResults()); |
| } catch (MiniLangException e) { |
| throw new GeneralException("Error running simple method at location [" + location + "]", e); |
| } |
| } else { |
| ScriptUtil.executeScript(this.location, this.method, context); |
| } |
| } |
| |
| public String getLocation() { |
| return location; |
| } |
| |
| public String getMethod() { |
| return method; |
| } |
| } |
| |
| /** |
| * Models the <service> element. |
| * |
| * @see <code>widget-screen.xsd</code> |
| */ |
| public static class Service extends AbstractModelAction { |
| private final FlexibleStringExpander autoFieldMapExdr; |
| private final Map<FlexibleMapAccessor<Object>, Object> fieldMap; |
| private final FlexibleMapAccessor<Map<String, Object>> resultMapNameAcsr; |
| private final FlexibleStringExpander serviceNameExdr; |
| |
| public Service(ModelWidget modelWidget, Element serviceElement) { |
| super(modelWidget, 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")); |
| this.fieldMap = EntityFinderUtil.makeFieldMap(serviceElement); |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public FlexibleStringExpander getServiceNameExdr() { |
| return this.serviceNameExdr; |
| } |
| |
| @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); |
| try { |
| Map<String, Object> serviceContext = null; |
| if ("true".equals(autoFieldMapString)) { |
| DispatchContext dc = WidgetWorker.getDispatcher(context).getDispatchContext(); |
| // try a map called "parameters", try it first so values from here are overriden by values in the main context |
| Map<String, Object> combinedMap = new HashMap<String, Object>(); |
| Map<String, Object> parametersObj = UtilGenerics.toMap(context.get("parameters")); |
| if (parametersObj != null) { |
| combinedMap.putAll(parametersObj); |
| } |
| combinedMap.putAll(context); |
| serviceContext = dc.makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, combinedMap); |
| } else if (UtilValidate.isNotEmpty(autoFieldMapString) && !"false".equals(autoFieldMapString)) { |
| FlexibleMapAccessor<Object> fieldFma = FlexibleMapAccessor.getInstance(autoFieldMapString); |
| Map<String, Object> autoFieldMap = UtilGenerics.toMap(fieldFma.get(context)); |
| if (autoFieldMap != null) { |
| serviceContext = WidgetWorker.getDispatcher(context).getDispatchContext() |
| .makeValidContext(serviceNameExpanded, ModelService.IN_PARAM, autoFieldMap); |
| } |
| } |
| if (serviceContext == null) { |
| serviceContext = new HashMap<String, Object>(); |
| } |
| if (this.fieldMap != null) { |
| EntityFinderUtil.expandFieldMapToContext(this.fieldMap, context, serviceContext); |
| } |
| Map<String, Object> 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); |
| } |
| } catch (GenericServiceException e) { |
| String errMsg = "Error calling service with name " + serviceNameExpanded + ": " + e.toString(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| |
| public FlexibleStringExpander getAutoFieldMapExdr() { |
| return autoFieldMapExdr; |
| } |
| |
| public Map<FlexibleMapAccessor<Object>, Object> getFieldMap() { |
| return fieldMap; |
| } |
| |
| public FlexibleMapAccessor<Map<String, Object>> getResultMapNameAcsr() { |
| return resultMapNameAcsr; |
| } |
| } |
| |
| /** |
| * Models the <set> element. |
| * |
| * @see <code>widget-common.xsd</code> |
| */ |
| public static class SetField extends AbstractModelAction { |
| private final FlexibleStringExpander defaultExdr; |
| private final FlexibleMapAccessor<Object> field; |
| private final FlexibleMapAccessor<Object> fromField; |
| private final String fromScope; |
| private final FlexibleStringExpander globalExdr; |
| private final String toScope; |
| private final String type; |
| private final FlexibleStringExpander valueExdr; |
| |
| public SetField(ModelWidget modelWidget, Element setElement) { |
| super(modelWidget, setElement); |
| this.field = FlexibleMapAccessor.getInstance(setElement.getAttribute("field")); |
| this.fromField = FlexibleMapAccessor.getInstance(setElement.getAttribute("from-field")); |
| this.valueExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("value")); |
| this.defaultExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("default-value")); |
| this.globalExdr = FlexibleStringExpander.getInstance(setElement.getAttribute("global")); |
| this.type = setElement.getAttribute("type"); |
| this.toScope = setElement.getAttribute("to-scope"); |
| this.fromScope = setElement.getAttribute("from-scope"); |
| if (!this.fromField.isEmpty() && !this.valueExdr.isEmpty()) { |
| throw new IllegalArgumentException("Cannot specify a from-field [" + setElement.getAttribute("from-field") |
| + "] and a value [" + setElement.getAttribute("value") + "] on the set action in a widget"); |
| } |
| } |
| |
| @Override |
| public void accept(ModelActionVisitor visitor) throws Exception { |
| visitor.visit(this); |
| } |
| |
| public Object getInMemoryPersistedFromField(Object storeAgent, Map<String, Object> context) { |
| Object newValue = null; |
| String originalName = this.fromField.getOriginalName(); |
| List<String> currentWidgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_")); |
| List<String> trailList = new ArrayList<String>(); |
| if (currentWidgetTrail != null) { |
| trailList.addAll(currentWidgetTrail); |
| } |
| for (int i = trailList.size(); i >= 0; i--) { |
| List<String> subTrail = trailList.subList(0, i); |
| String newKey = null; |
| if (subTrail.size() > 0) |
| newKey = StringUtil.join(subTrail, "|") + "|" + originalName; |
| else |
| newKey = originalName; |
| if (storeAgent instanceof ServletContext) { |
| newValue = ((ServletContext) storeAgent).getAttribute(newKey); |
| } else if (storeAgent instanceof HttpSession) { |
| newValue = ((HttpSession) storeAgent).getAttribute(newKey); |
| } |
| if (newValue != null) { |
| break; |
| } |
| } |
| return newValue; |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @Override |
| public void runAction(Map<String, Object> context) { |
| String globalStr = this.globalExdr.expandString(context); |
| // default to false |
| boolean global = "true".equals(globalStr); |
| Object newValue = null; |
| if (this.fromScope != null && this.fromScope.equals("user")) { |
| if (!this.fromField.isEmpty()) { |
| HttpSession session = (HttpSession) context.get("session"); |
| newValue = getInMemoryPersistedFromField(session, context); |
| if (Debug.verboseOn()) |
| Debug.logVerbose("In user getting value for field from [" + this.fromField.getOriginalName() + "]: " |
| + newValue, module); |
| } else if (!this.valueExdr.isEmpty()) { |
| newValue = this.valueExdr.expand(context); |
| } |
| } else if (this.fromScope != null && this.fromScope.equals("application")) { |
| if (!this.fromField.isEmpty()) { |
| ServletContext servletContext = (ServletContext) context.get("application"); |
| newValue = getInMemoryPersistedFromField(servletContext, context); |
| if (Debug.verboseOn()) |
| Debug.logVerbose("In application getting value for field from [" + this.fromField.getOriginalName() |
| + "]: " + newValue, module); |
| } else if (!this.valueExdr.isEmpty()) { |
| newValue = this.valueExdr.expandString(context); |
| } |
| } else { |
| if (!this.fromField.isEmpty()) { |
| newValue = this.fromField.get(context); |
| if (Debug.verboseOn()) |
| Debug.logVerbose("Getting value for field from [" + this.fromField.getOriginalName() + "]: " + newValue, |
| module); |
| } else if (!this.valueExdr.isEmpty()) { |
| newValue = this.valueExdr.expand(context); |
| } |
| } |
| // If newValue is still empty, use the default value |
| if (ObjectType.isEmpty(newValue) && !this.defaultExdr.isEmpty()) { |
| newValue = this.defaultExdr.expand(context); |
| } |
| if (UtilValidate.isNotEmpty(this.type)) { |
| if ("NewMap".equals(this.type)) { |
| newValue = new HashMap(); |
| } else if ("NewList".equals(this.type)) { |
| newValue = new LinkedList(); |
| } else { |
| try { |
| newValue = ObjectType.simpleTypeConvert(newValue, this.type, null, (TimeZone) context.get("timeZone"), |
| (Locale) context.get("locale"), true); |
| } catch (GeneralException e) { |
| String errMsg = "Could not convert field value for the field: [" + this.field.getOriginalName() |
| + "] to the [" + this.type + "] type for the value [" + newValue + "]: " + e.toString(); |
| Debug.logError(e, errMsg, module); |
| throw new IllegalArgumentException(errMsg); |
| } |
| } |
| } |
| if (this.toScope != null && this.toScope.equals("user")) { |
| String originalName = this.field.getOriginalName(); |
| List<String> currentWidgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_")); |
| String newKey = ""; |
| if (currentWidgetTrail != null) { |
| newKey = StringUtil.join(currentWidgetTrail, "|"); |
| } |
| if (UtilValidate.isNotEmpty(newKey)) { |
| newKey += "|"; |
| } |
| newKey += originalName; |
| HttpSession session = (HttpSession) context.get("session"); |
| session.setAttribute(newKey, newValue); |
| if (Debug.verboseOn()) |
| Debug.logVerbose("In user setting value for field from [" + this.field.getOriginalName() + "]: " + newValue, |
| module); |
| } else if (this.toScope != null && this.toScope.equals("application")) { |
| String originalName = this.field.getOriginalName(); |
| List<String> currentWidgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_")); |
| String newKey = ""; |
| if (currentWidgetTrail != null) { |
| newKey = StringUtil.join(currentWidgetTrail, "|"); |
| } |
| if (UtilValidate.isNotEmpty(newKey)) { |
| newKey += "|"; |
| } |
| newKey += originalName; |
| ServletContext servletContext = (ServletContext) context.get("application"); |
| servletContext.setAttribute(newKey, newValue); |
| if (Debug.verboseOn()) |
| Debug.logVerbose("In application setting value for field from [" + this.field.getOriginalName() + "]: " |
| + newValue, module); |
| } else { |
| // only do this if it is not global, if global ONLY put it in the global context |
| if (!global) { |
| if (Debug.verboseOn()) |
| Debug.logVerbose("Setting field [" + this.field.getOriginalName() + "] to value: " + newValue, module); |
| this.field.put(context, newValue); |
| } |
| } |
| if (global) { |
| Map<String, Object> globalCtx = UtilGenerics.checkMap(context.get("globalContext")); |
| if (globalCtx != null) { |
| this.field.put(globalCtx, newValue); |
| } else { |
| this.field.put(context, newValue); |
| } |
| } |
| } |
| |
| public FlexibleStringExpander getDefaultExdr() { |
| return defaultExdr; |
| } |
| |
| public FlexibleMapAccessor<Object> getField() { |
| return field; |
| } |
| |
| public FlexibleMapAccessor<Object> getFromField() { |
| return fromField; |
| } |
| |
| public String getFromScope() { |
| return fromScope; |
| } |
| |
| public FlexibleStringExpander getGlobalExdr() { |
| return globalExdr; |
| } |
| |
| public String getToScope() { |
| return toScope; |
| } |
| |
| public String getType() { |
| return type; |
| } |
| |
| public FlexibleStringExpander getValueExdr() { |
| return valueExdr; |
| } |
| } |
| } |