/******************************************************************************* * 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.math.BigDecimal; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import org.apache.ofbiz.base.util.Debug; import org.apache.ofbiz.base.util.UtilCodec; import org.apache.ofbiz.base.util.UtilDateTime; 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.string.FlexibleStringExpander; import org.apache.ofbiz.entity.Delegator; import org.apache.ofbiz.entity.GenericValue; import org.apache.ofbiz.entity.model.ModelEntity; import org.apache.ofbiz.entity.model.ModelField; import org.apache.ofbiz.service.GenericServiceException; import org.apache.ofbiz.service.LocalDispatcher; import org.apache.ofbiz.service.ModelParam; import org.apache.ofbiz.service.ModelService; import org.w3c.dom.Element; /** * A collection of shared/reused widget models. * */ public final class CommonWidgetModels { public static final String module = CommonWidgetModels.class.getName(); private CommonWidgetModels() { } public static class AutoEntityParameters { private String entityName; List<String> excludeList = new ArrayList<String>(); boolean includeNonPk; boolean includePk; private String includeType; boolean sendIfEmpty; public AutoEntityParameters(Element autoElement) { entityName = UtilXml.checkEmpty(autoElement.getAttribute("entity-name")); sendIfEmpty = "true".equals(autoElement.getAttribute("send-if-empty")); includeType = UtilXml.checkEmpty(autoElement.getAttribute("include")); includePk = "pk".equals(includeType) || "all".equals(includeType); includeNonPk = "nonpk".equals(includeType) || "all".equals(includeType); List<? extends Element> excludes = UtilXml.childElementList(autoElement, "exclude"); if (excludes != null) { for (Element exclude : excludes) { if (UtilValidate.isNotEmpty(exclude.getAttribute("field-name"))) { excludeList.add(exclude.getAttribute("field-name")); } } } } @SuppressWarnings("unchecked") public Map<String, String> getParametersMap(Map<String, Object> context, String defaultEntityName) { Map<String, String> autEntityParams = new HashMap<String, String>(); Delegator delegator = (Delegator) context.get("delegator"); if (delegator == null) { Debug.logError( "We can not append auto entity Parameters since we could not find delegator in the current context", module); return autEntityParams; } if (UtilValidate.isEmpty(entityName)) entityName = defaultEntityName; FlexibleStringExpander toExpand = FlexibleStringExpander.getInstance(entityName); ModelEntity entity = delegator.getModelEntity(toExpand.expandString(context)); if (entity == null) { Debug.logError("We can not append auto entity Parameters since we could not find entity with name [" + entityName + "]", module); return autEntityParams; } Iterator<ModelField> fieldsIter = entity.getFieldsIterator(); if (fieldsIter != null) { while (fieldsIter.hasNext()) { ModelField field = fieldsIter.next(); String fieldName = field.getName(); FlexibleMapAccessor<Object> fma = FlexibleMapAccessor.getInstance(fieldName); boolean shouldExclude = excludeList.contains(fieldName); if ((!shouldExclude) && (!field.getIsAutoCreatedInternal()) && ((field.getIsPk() && includePk) || (!field.getIsPk() && includeNonPk))) { Object flexibleValue = fma.get(context); if (UtilValidate.isEmpty(flexibleValue) && context.containsKey("parameters")) { flexibleValue = fma.get((Map<String, Object>) context.get("parameters")); } if (UtilValidate.isNotEmpty(flexibleValue) || sendIfEmpty) { autEntityParams.put(fieldName, String.valueOf(flexibleValue)); } } } } return autEntityParams; } } public static class AutoServiceParameters { List<String> excludeList = new ArrayList<String>(); boolean includeNonPk; boolean includePk; boolean sendIfEmpty; private String serviceName; public AutoServiceParameters(Element autoElement) { serviceName = UtilXml.checkEmpty(autoElement.getAttribute("service-name")); sendIfEmpty = "true".equals(autoElement.getAttribute("send-if-empty")); List<? extends Element> excludes = UtilXml.childElementList(autoElement, "exclude"); if (excludes != null) { for (Element exclude : excludes) { if (UtilValidate.isNotEmpty(exclude.getAttribute("field-name"))) { excludeList.add(exclude.getAttribute("field-name")); } } } } @SuppressWarnings("unchecked") public Map<String, String> getParametersMap(Map<String, Object> context, String defaultServiceName) { Map<String, String> autServiceParams = new HashMap<String, String>(); LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher"); if (dispatcher == null) { Debug.logError( "We can not append auto service Parameters since we could not find dispatcher in the current context", module); return autServiceParams; } if (UtilValidate.isEmpty(serviceName)) serviceName = defaultServiceName; FlexibleStringExpander toExpand = FlexibleStringExpander.getInstance(serviceName); ModelService service = null; try { service = dispatcher.getDispatchContext().getModelService(toExpand.toString()); } catch (GenericServiceException e) { Debug.logError("Resolve service throw an error : " + e, module); } if (service == null) { Debug.logError("We can not append auto service Parameters since we could not find service with name [" + serviceName + "]", module); return autServiceParams; } Iterator<ModelParam> paramsIter = service.getInModelParamList().iterator(); if (paramsIter != null) { while (paramsIter.hasNext()) { ModelParam param = paramsIter.next(); if (param.getInternal()) continue; String paramName = param.getName(); FlexibleMapAccessor<Object> fma = FlexibleMapAccessor.getInstance(paramName); if (!excludeList.contains(paramName)) { Object flexibleValue = fma.get(context); if (UtilValidate.isEmpty(flexibleValue) && context.containsKey("parameters")) { flexibleValue = fma.get((Map<String, ? extends Object>) context.get("parameters")); } if (UtilValidate.isNotEmpty(flexibleValue) || sendIfEmpty) { autServiceParams.put(paramName, String.valueOf(flexibleValue)); } } } } return autServiceParams; } } public static final class Image { private final FlexibleStringExpander alt; private final FlexibleStringExpander borderExdr; private final FlexibleStringExpander heightExdr; private final FlexibleStringExpander idExdr; private final String name; private final FlexibleStringExpander srcExdr; private final FlexibleStringExpander styleExdr; private final FlexibleStringExpander titleExdr; private final String urlMode; private final FlexibleStringExpander widthExdr; public Image(Element imageElement) { if (!imageElement.getAttribute("image-location").isEmpty()) { // Form field version, log warning. this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("image-location")); this.alt = FlexibleStringExpander.getInstance(imageElement.getAttribute("alternate")); this.titleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("image-title")); this.name = ""; this.idExdr = FlexibleStringExpander.getInstance(""); this.styleExdr = FlexibleStringExpander.getInstance(""); this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width")); this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height")); this.borderExdr = FlexibleStringExpander.getInstance(""); this.urlMode = "content"; } else { this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("src")); this.alt = FlexibleStringExpander.getInstance(imageElement.getAttribute("alt")); this.titleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("title")); this.name = imageElement.getAttribute("name"); this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id")); this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style")); this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width")); this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height")); this.borderExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("border")); String urlMode = imageElement.getAttribute("url-mode"); if (urlMode.isEmpty()) { urlMode = "content"; } this.urlMode = urlMode; } } public FlexibleStringExpander getAlt() { return alt; } public String getAlt(Map<String, Object> context) { String alt = this.alt.expandString(context); // FIXME: Encoding should be done by the renderer, not by the model. UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder"); if (simpleEncoder != null) { alt = simpleEncoder.encode(alt); } return alt; } public String getBorder(Map<String, Object> context) { return this.borderExdr.expandString(context); } public FlexibleStringExpander getBorderExdr() { return borderExdr; } public String getHeight(Map<String, Object> context) { return this.heightExdr.expandString(context); } public FlexibleStringExpander getHeightExdr() { return heightExdr; } public String getId(Map<String, Object> context) { return this.idExdr.expandString(context); } public FlexibleStringExpander getIdExdr() { return idExdr; } public String getName() { return name; } public String getSrc(Map<String, Object> context) { return this.srcExdr.expandString(context); } public FlexibleStringExpander getSrcExdr() { return srcExdr; } public String getStyle(Map<String, Object> context) { return this.styleExdr.expandString(context); } public FlexibleStringExpander getStyleExdr() { return styleExdr; } public FlexibleStringExpander getTitleExdr() { return titleExdr; } public String getUrlMode() { return this.urlMode; } public String getWidth(Map<String, Object> context) { return this.widthExdr.expandString(context); } public FlexibleStringExpander getWidthExdr() { return widthExdr; } } public static final class Link { // FIXME: This is a bad practice. Client code should not need to "know" what this value is. public static final String DEFAULT_URL_MODE = "intra-app"; private final AutoEntityParameters autoEntityParameters; private final AutoServiceParameters autoServiceParameters; private final boolean encode; private final boolean fullPath; private final FlexibleStringExpander idExdr; private final Image image; private final String linkType; // anchor or hidden form private final FlexibleStringExpander nameExdr; private final List<Parameter> parameterList; private final FlexibleStringExpander prefixExdr; private final boolean secure; private final Integer size; private final FlexibleStringExpander styleExdr; private final FlexibleStringExpander targetExdr; private final FlexibleStringExpander targetWindowExdr; private final FlexibleStringExpander textExdr; private final String urlMode; private final boolean requestConfirmation; private final FlexibleStringExpander confirmationMsgExdr; // FIXME: These don't belong in this class (might have been used for image) private final String height; private final String width; public Link(Element linkElement) { this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text")); this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id")); this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style")); this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name")); this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target")); this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window")); this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix")); this.urlMode = linkElement.getAttribute("url-mode"); this.fullPath = "true".equals(linkElement.getAttribute("full-path")); this.secure = "true".equals(linkElement.getAttribute("secure")); this.encode = "true".equals(linkElement.getAttribute("encode")); Element imageElement = UtilXml.firstChildElement(linkElement, "image"); if (imageElement != null) { this.image = new Image(imageElement); } else { if (!linkElement.getAttribute("image-location").isEmpty()) { // Backwards compatibility this.image = new Image(linkElement); } else { this.image = null; } } //Backwards compatibility if ("ajax-window".equals(linkElement.getAttribute("link-type"))) this.linkType = "layered-modal"; else this.linkType = linkElement.getAttribute("link-type"); List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter"); if (parameterElementList.isEmpty()) { this.parameterList = Collections.emptyList(); } else { List<Parameter> parameterList = new ArrayList<Parameter>( parameterElementList.size()); for (Element parameterElement : parameterElementList) { parameterList.add(new Parameter(parameterElement)); } this.parameterList = Collections.unmodifiableList(parameterList); } Element autoServiceParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-service"); if (autoServiceParamsElement != null) { this.autoServiceParameters = new AutoServiceParameters(autoServiceParamsElement); } else { this.autoServiceParameters = null; } Element autoEntityParamsElement = UtilXml.firstChildElement(linkElement, "auto-parameters-entity"); if (autoEntityParamsElement != null) { this.autoEntityParameters = new AutoEntityParameters(autoEntityParamsElement); } else { this.autoEntityParameters = null; } Integer size = null; String sizeAttr = linkElement.getAttribute("size"); if (!sizeAttr.isEmpty()) { size = Integer.valueOf(sizeAttr); } this.size = size; this.requestConfirmation = "true".equals(linkElement.getAttribute("request-confirmation")); this.confirmationMsgExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("confirmation-message")); this.width = linkElement.getAttribute("width"); this.height = linkElement.getAttribute("height"); } // Portal constructor public Link(GenericValue portalPage, List<Parameter> parameterList, String target, Locale locale) { this.autoEntityParameters = null; this.autoServiceParameters = null; this.encode = false; this.fullPath = false; this.idExdr = FlexibleStringExpander.getInstance(""); this.image = null; this.linkType = ""; this.nameExdr = FlexibleStringExpander.getInstance(""); this.parameterList = Collections.unmodifiableList(parameterList); this.prefixExdr = FlexibleStringExpander.getInstance(""); this.secure = false; this.styleExdr = FlexibleStringExpander.getInstance(""); this.targetExdr = FlexibleStringExpander.getInstance(target); this.targetWindowExdr = FlexibleStringExpander.getInstance(""); this.textExdr = FlexibleStringExpander.getInstance((String) portalPage.get("portalPageName", locale)); this.urlMode = "intra-app"; this.size = null; this.requestConfirmation = false; this.confirmationMsgExdr = FlexibleStringExpander.getInstance(""); this.width = ""; this.height = ""; } public AutoEntityParameters getAutoEntityParameters() { return autoEntityParameters; } public AutoServiceParameters getAutoServiceParameters() { return autoServiceParameters; } public String getConfirmationMsg(Map<String, Object> context) { return this.confirmationMsgExdr.expandString(context); } public FlexibleStringExpander getConfirmationMsgExdr() { return confirmationMsgExdr; } public boolean getEncode() { return this.encode; } public boolean getFullPath() { return this.fullPath; } public String getHeight() { return this.height; } public String getId(Map<String, Object> context) { return this.idExdr.expandString(context); } public FlexibleStringExpander getIdExdr() { return idExdr; } public Image getImage() { return this.image; } public String getLinkType() { return this.linkType; } public String getName() { return nameExdr.getOriginal(); } public String getName(Map<String, Object> context) { return this.nameExdr.expandString(context); } public FlexibleStringExpander getNameExdr() { return nameExdr; } public List<Parameter> getParameterList() { return parameterList; } public Map<String, String> getParameterMap(Map<String, Object> context, String defaultEntityName, String defaultServiceName) { Map<String, String> fullParameterMap = new HashMap<String, String>(); for (Parameter parameter : this.parameterList) { fullParameterMap.put(parameter.getName(), parameter.getValue(context)); } if (autoServiceParameters != null) { fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, defaultServiceName)); } if (autoEntityParameters != null) { fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, defaultEntityName)); } return fullParameterMap; } public Map<String, String> getParameterMap(Map<String, Object> context) { Map<String, String> fullParameterMap = new HashMap<String, String>(); for (Parameter parameter : this.parameterList) { fullParameterMap.put(parameter.getName(), parameter.getValue(context)); } if (autoServiceParameters != null) { fullParameterMap.putAll(autoServiceParameters.getParametersMap(context, null)); } if (autoEntityParameters != null) { fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, null)); } return fullParameterMap; } public String getPrefix(Map<String, Object> context) { return this.prefixExdr.expandString(context); } public FlexibleStringExpander getPrefixExdr() { return prefixExdr; } public boolean getRequestConfirmation() { return this.requestConfirmation; } public boolean getSecure() { return this.secure; } public Integer getSize() { return size; } public String getStyle(Map<String, Object> context) { return this.styleExdr.expandString(context); } public FlexibleStringExpander getStyleExdr() { return styleExdr; } public String getTarget(Map<String, Object> context) { Map<String, Object> expanderContext = context; UtilCodec.SimpleEncoder simpleEncoder = context == null ? null : (UtilCodec.SimpleEncoder) context .get("simpleEncoder"); if (simpleEncoder != null) { expanderContext = UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, simpleEncoder); } return this.targetExdr.expandString(expanderContext); } public FlexibleStringExpander getTargetExdr() { return targetExdr; } public String getTargetWindow(Map<String, Object> context) { return this.targetWindowExdr.expandString(context); } public FlexibleStringExpander getTargetWindowExdr() { return targetWindowExdr; } public String getText(Map<String, Object> context) { String text = this.textExdr.expandString(context); // FIXME: Encoding should be done by the renderer, not by the model. UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder"); if (simpleEncoder != null) { text = simpleEncoder.encode(text); } return text; } public FlexibleStringExpander getTextExdr() { return textExdr; } public String getUrlMode() { return this.urlMode; } public String getWidth() { return this.width; } } /** * Models the <parameter> element. * * @see <code>widget-form.xsd</code> */ public static class Parameter { protected FlexibleMapAccessor<Object> fromField; protected String name; protected FlexibleStringExpander value; public Parameter(Element element) { this.name = element.getAttribute("param-name"); this.value = UtilValidate.isNotEmpty(element.getAttribute("value")) ? FlexibleStringExpander.getInstance(element .getAttribute("value")) : null; this.fromField = UtilValidate.isNotEmpty(element.getAttribute("from-field")) ? FlexibleMapAccessor .getInstance(element.getAttribute("from-field")) : null; } public Parameter(String paramName, String paramValue, boolean isField) { this.name = paramName; if (isField) { this.fromField = FlexibleMapAccessor.getInstance(paramValue); } else { this.value = FlexibleStringExpander.getInstance(paramValue); } } public FlexibleMapAccessor<Object> getFromField() { return fromField; } public String getName() { return name; } public FlexibleStringExpander getValue() { return value; } public String getValue(Map<String, Object> context) { if (this.value != null) { return this.value.expandString(context); } Object retVal = null; if (this.fromField != null && this.fromField.get(context) != null) { retVal = this.fromField.get(context); } else { retVal = context.get(this.name); } if (retVal != null) { TimeZone timeZone = (TimeZone) context.get("timeZone"); if (timeZone == null) timeZone = TimeZone.getDefault(); String returnValue = null; // format string based on the user's time zone (not locale because these are parameters) if (retVal instanceof Double || retVal instanceof Float || retVal instanceof BigDecimal) { returnValue = retVal.toString(); } else if (retVal instanceof java.sql.Date) { DateFormat df = UtilDateTime.toDateFormat(UtilDateTime.getDateFormat(), timeZone, null); returnValue = df.format((java.util.Date) retVal); } else if (retVal instanceof java.sql.Time) { DateFormat df = UtilDateTime.toTimeFormat(UtilDateTime.getTimeFormat(), timeZone, null); returnValue = df.format((java.util.Date) retVal); } else if (retVal instanceof java.sql.Timestamp) { DateFormat df = UtilDateTime.toDateTimeFormat(UtilDateTime.getDateTimeFormat(), timeZone, null); returnValue = df.format((java.util.Date) retVal); } else if (retVal instanceof java.util.Date) { DateFormat df = UtilDateTime.toDateTimeFormat("EEE MMM dd hh:mm:ss z yyyy", timeZone, null); returnValue = df.format((java.util.Date) retVal); } else { returnValue = retVal.toString(); } return returnValue; } else { return null; } } } }