Added: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java?rev=1652852&view=auto ============================================================================== --- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java (added) +++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/model/ModelScreenWidget.java Sun Jan 18 21:03:40 2015 @@ -0,0 +1,1957 @@ +/******************************************************************************* + * 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.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.GeneralException; +import org.ofbiz.base.util.UtilCodec; +import org.ofbiz.base.util.UtilGenerics; +import org.ofbiz.base.util.UtilXml; +import org.ofbiz.base.util.collections.MapStack; +import org.ofbiz.base.util.string.FlexibleStringExpander; +import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntityException; +import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.util.EntityQuery; +import org.ofbiz.widget.WidgetFactory; +import org.ofbiz.widget.model.CommonWidgetModels.AutoEntityParameters; +import org.ofbiz.widget.model.CommonWidgetModels.AutoServiceParameters; +import org.ofbiz.widget.model.CommonWidgetModels.Image; +import org.ofbiz.widget.model.CommonWidgetModels.Link; +import org.ofbiz.widget.model.CommonWidgetModels.Parameter; +import org.ofbiz.widget.portal.PortalPageWorker; +import org.ofbiz.widget.renderer.FormRenderer; +import org.ofbiz.widget.renderer.FormStringRenderer; +import org.ofbiz.widget.renderer.MenuStringRenderer; +import org.ofbiz.widget.renderer.ScreenRenderer; +import org.ofbiz.widget.renderer.ScreenStringRenderer; +import org.ofbiz.widget.renderer.TreeStringRenderer; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + + +/** + * Widget Library - Screen model class + */ +@SuppressWarnings("serial") +public abstract class ModelScreenWidget extends ModelWidget { + public static final String module = ModelScreenWidget.class.getName(); + + private final ModelScreen modelScreen; + + public ModelScreenWidget(ModelScreen modelScreen, Element widgetElement) { + super(widgetElement); + this.modelScreen = modelScreen; + if (Debug.verboseOn()) Debug.logVerbose("Reading Screen sub-widget with name: " + widgetElement.getNodeName(), module); + } + + public abstract void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException; + + protected static List<ModelScreenWidget> readSubWidgets(ModelScreen modelScreen, List<? extends Element> subElementList) { + if (subElementList.isEmpty()) { + return Collections.emptyList(); + } + List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(subElementList.size()); + for (Element subElement: subElementList) { + subWidgets.add(WidgetFactory.getModelScreenWidget(modelScreen, subElement)); + } + return Collections.unmodifiableList(subWidgets); + } + + protected static void renderSubWidgetsString(List<ModelScreenWidget> subWidgets, Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + if (subWidgets == null) { + return; + } + for (ModelScreenWidget subWidget: subWidgets) { + if (Debug.verboseOn()) Debug.logVerbose("Rendering screen " + subWidget.getModelScreen().getName() + "; widget class is " + subWidget.getClass().getName(), module); + + // render the sub-widget itself + subWidget.renderWidgetString(writer, context, screenStringRenderer); + } + } + + public ModelScreen getModelScreen() { + return this.modelScreen; + } + + public static final class SectionsRenderer implements Map<String, ModelScreenWidget> { + private final Map<String, ModelScreenWidget> sectionMap; + private final ScreenStringRenderer screenStringRenderer; + private final Map<String, Object> context; + private final Appendable writer; + + public SectionsRenderer(Map<String, ModelScreenWidget> sectionMap, Map<String, Object> context, Appendable writer, + ScreenStringRenderer screenStringRenderer) { + Map<String, ModelScreenWidget> localMap = new HashMap<String, ModelScreenWidget>(); + localMap.putAll(sectionMap); + this.sectionMap = Collections.unmodifiableMap(localMap); + this.context = context; + this.writer = writer; + this.screenStringRenderer = screenStringRenderer; + } + + /** This is a lot like the ScreenRenderer class and returns an empty String so it can be used more easily with FreeMarker */ + public String render(String sectionName) throws GeneralException, IOException { + ModelScreenWidget section = sectionMap.get(sectionName); + // if no section by that name, write nothing + if (section != null) { + section.renderWidgetString(this.writer, this.context, this.screenStringRenderer); + } + return ""; + } + + @Override + public int size() { + return sectionMap.size(); + } + + @Override + public boolean isEmpty() { + return sectionMap.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return sectionMap.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return sectionMap.containsValue(value); + } + + @Override + public ModelScreenWidget get(Object key) { + return sectionMap.get(key); + } + + @Override + public ModelScreenWidget put(String key, ModelScreenWidget value) { + return sectionMap.put(key, value); + } + + @Override + public ModelScreenWidget remove(Object key) { + return sectionMap.remove(key); + } + + @Override + public void clear() { + sectionMap.clear(); + } + + @Override + public Set<String> keySet() { + return sectionMap.keySet(); + } + + @Override + public Collection<ModelScreenWidget> values() { + return sectionMap.values(); + } + + @Override + public Set<java.util.Map.Entry<String, ModelScreenWidget>> entrySet() { + return sectionMap.entrySet(); + } + + @Override + public boolean equals(Object o) { + return sectionMap.equals(o); + } + + @Override + public int hashCode() { + return sectionMap.hashCode(); + } + + @Override + public void putAll(Map<? extends String, ? extends ModelScreenWidget> m) { + sectionMap.putAll(m); + } + } + + public static final class Section extends ModelScreenWidget { + public static final String TAG_NAME = "section"; + private final ModelCondition condition; + private final List<ModelAction> actions; + private final List<ModelScreenWidget> subWidgets; + private final List<ModelScreenWidget> failWidgets; + private final boolean isMainSection; + + public Section(ModelScreen modelScreen, Element sectionElement) { + this(modelScreen, sectionElement, false); + } + + public Section(ModelScreen modelScreen, Element sectionElement, boolean isMainSection) { + super(modelScreen, sectionElement); + + // read condition under the "condition" element + Element conditionElement = UtilXml.firstChildElement(sectionElement, "condition"); + if (conditionElement != null) { + conditionElement = UtilXml.firstChildElement(conditionElement); + this.condition = ModelScreenCondition.SCREEN_CONDITION_FACTORY.newInstance(modelScreen, conditionElement); + } else { + this.condition = null; + } + + // read all actions under the "actions" element + Element actionsElement = UtilXml.firstChildElement(sectionElement, "actions"); + if (actionsElement != null) { + this.actions = AbstractModelAction.readSubActions(modelScreen, actionsElement); + } else { + this.actions = Collections.emptyList(); + } + + // read sub-widgets + Element widgetsElement = UtilXml.firstChildElement(sectionElement, "widgets"); + if (widgetsElement != null) { + List<? extends Element> subElementList = UtilXml.childElementList(widgetsElement); + this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList); + } else { + this.subWidgets = Collections.emptyList(); + } + + // read fail-widgets + Element failWidgetsElement = UtilXml.firstChildElement(sectionElement, "fail-widgets"); + if (failWidgetsElement != null) { + List<? extends Element> failElementList = UtilXml.childElementList(failWidgetsElement); + this.failWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), failElementList); + } else { + this.failWidgets = Collections.emptyList(); + } + this.isMainSection = isMainSection; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + // check the condition, if there is one + boolean condTrue = true; + if (this.condition != null) { + if (!this.condition.eval(context)) { + condTrue = false; + } + } + + // if condition does not exist or evals to true run actions and render widgets, otherwise render fail-widgets + if (condTrue) { + // run the actions only if true + AbstractModelAction.runSubActions(this.actions, context); + + try { + // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway + screenStringRenderer.renderSectionBegin(writer, context, this); + + // render sub-widgets + renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer); + + screenStringRenderer.renderSectionEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering widgets section [" + getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } else { + try { + // section by definition do not themselves do anything, so this method will generally do nothing, but we'll call it anyway + screenStringRenderer.renderSectionBegin(writer, context, this); + + // render sub-widgets + renderSubWidgetsString(this.failWidgets, writer, context, screenStringRenderer); + + screenStringRenderer.renderSectionEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering fail-widgets section [" + this.getName() + "] in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + } + + @Override + public String getBoundaryCommentName() { + if (isMainSection) { + return getModelScreen().getSourceLocation() + "#" + getModelScreen().getName(); + } else { + return getName(); + } + } + + public List<ModelAction> getActions() { + return actions; + } + + public List<ModelScreenWidget> getSubWidgets() { + return subWidgets; + } + + public List<ModelScreenWidget> getFailWidgets() { + return failWidgets; + } + + public boolean isMainSection() { + return isMainSection; + } + + public ModelCondition getCondition() { + return condition; + } + } + + public static final class ColumnContainer extends ModelScreenWidget { + public static final String TAG_NAME = "column-container"; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander styleExdr; + private final List<Column> columns; + + public ColumnContainer(ModelScreen modelScreen, Element containerElement) { + super(modelScreen, containerElement); + this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id")); + this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style")); + List<? extends Element> subElementList = UtilXml.childElementList(containerElement, "column"); + List<Column> columns = new ArrayList<Column>(subElementList.size()); + for (Element element : subElementList) { + columns.add(new Column(modelScreen, element)); + } + this.columns = Collections.unmodifiableList(columns); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + try { + screenStringRenderer.renderColumnContainer(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + public List<Column> getColumns() { + return this.columns; + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getStyle(Map<String, Object> context) { + return this.styleExdr.expandString(context); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getStyleExdr() { + return styleExdr; + } + } + + public static final class Column extends ModelWidget { + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander styleExdr; + private final List<ModelScreenWidget> subWidgets; + + public Column(ModelScreen modelScreen, Element columnElement) { + super(columnElement); + this.idExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("id")); + this.styleExdr = FlexibleStringExpander.getInstance(columnElement.getAttribute("style")); + List<? extends Element> subElementList = UtilXml.childElementList(columnElement); + this.subWidgets = Collections.unmodifiableList(readSubWidgets(modelScreen, subElementList)); + } + + public List<ModelScreenWidget> getSubWidgets() { + return this.subWidgets; + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getStyle(Map<String, Object> context) { + return this.styleExdr.expandString(context); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getStyleExdr() { + return styleExdr; + } + } + + public static final class Container extends ModelScreenWidget { + public static final String TAG_NAME = "container"; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander styleExdr; + private final FlexibleStringExpander autoUpdateTargetExdr; + private final FlexibleStringExpander autoUpdateInterval; + private final List<ModelScreenWidget> subWidgets; + + public Container(ModelScreen modelScreen, Element containerElement) { + super(modelScreen, containerElement); + this.idExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("id")); + this.styleExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("style")); + this.autoUpdateTargetExdr = FlexibleStringExpander.getInstance(containerElement.getAttribute("auto-update-target")); + String autoUpdateInterval = containerElement.getAttribute("auto-update-interval"); + if (autoUpdateInterval.isEmpty()) { + autoUpdateInterval = "2"; + } + this.autoUpdateInterval = FlexibleStringExpander.getInstance(autoUpdateInterval); + // read sub-widgets + List<? extends Element> subElementList = UtilXml.childElementList(containerElement); + this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + try { + screenStringRenderer.renderContainerBegin(writer, context, this); + + // render sub-widgets + renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer); + + screenStringRenderer.renderContainerEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering container in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getStyle(Map<String, Object> context) { + return this.styleExdr.expandString(context); + } + + public String getAutoUpdateTargetExdr(Map<String, Object> context) { + return this.autoUpdateTargetExdr.expandString(context); + } + + public String getAutoUpdateInterval(Map<String, Object> context) { + return this.autoUpdateInterval.expandString(context); + } + + public List<ModelScreenWidget> getSubWidgets() { + return subWidgets; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getStyleExdr() { + return styleExdr; + } + + public FlexibleStringExpander getAutoUpdateTargetExdr() { + return autoUpdateTargetExdr; + } + + public FlexibleStringExpander getAutoUpdateInterval() { + return autoUpdateInterval; + } + } + + public static final class Screenlet extends ModelScreenWidget { + public static final String TAG_NAME = "screenlet"; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander titleExdr; + private final Menu navigationMenu; + private final Menu tabMenu; + private final Form navigationForm; + private final boolean collapsible; + private final FlexibleStringExpander initiallyCollapsed; + private final boolean saveCollapsed; + private final boolean padded; + private final List<ModelScreenWidget> subWidgets; + + public Screenlet(ModelScreen modelScreen, Element screenletElement) { + super(modelScreen, screenletElement); + this.idExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("id")); + boolean collapsible = "true".equals(screenletElement.getAttribute("collapsible")); + this.initiallyCollapsed = FlexibleStringExpander.getInstance(screenletElement.getAttribute("initially-collapsed")); + if ("true".equals(this.initiallyCollapsed.getOriginal())) { + collapsible = true; + } + this.collapsible = collapsible; + // By default, for a collapsible screenlet, the collapsed/expanded status must be saved + this.saveCollapsed = !("false".equals(screenletElement.getAttribute("save-collapsed"))); + + boolean padded = !"false".equals(screenletElement.getAttribute("padded")); + if (this.collapsible && getName().isEmpty() && idExdr.isEmpty()) { + throw new IllegalArgumentException("Collapsible screenlets must have a name or id [" + getModelScreen().getName() + "]"); + } + this.titleExdr = FlexibleStringExpander.getInstance(screenletElement.getAttribute("title")); + List<? extends Element> subElementList = UtilXml.childElementList(screenletElement); + // Make a copy of the unmodifiable List so we can modify it. + ArrayList<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>(ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList)); + Menu navigationMenu = null; + String navMenuName = screenletElement.getAttribute("navigation-menu-name"); + if (!navMenuName.isEmpty()) { + for (ModelWidget subWidget : subWidgets) { + if (navMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) { + navigationMenu = (Menu) subWidget; + subWidgets.remove(subWidget); + break; + } + } + } + this.navigationMenu = navigationMenu; + Menu tabMenu = null; + String tabMenuName = screenletElement.getAttribute("tab-menu-name"); + if (!tabMenuName.isEmpty()) { + for (ModelWidget subWidget : subWidgets) { + if (tabMenuName.equals(subWidget.getName()) && subWidget instanceof Menu) { + tabMenu = (Menu) subWidget; + subWidgets.remove(subWidget); + break; + } + } + } + this.tabMenu = tabMenu; + Form navigationForm = null; + String formName = screenletElement.getAttribute("navigation-form-name"); + if (!formName.isEmpty() && this.navigationMenu == null) { + for (ModelWidget subWidget : subWidgets) { + if (formName.equals(subWidget.getName()) && subWidget instanceof Form) { + navigationForm = (Form) subWidget; + padded = false; + break; + } + } + } + this.subWidgets = Collections.unmodifiableList(subWidgets); + this.navigationForm = navigationForm; + this.padded = padded; + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + boolean collapsed = getInitiallyCollapsed(context); + if (this.collapsible) { + String preferenceKey = getPreferenceKey(context) + "_collapsed"; + Map<String, Object> requestParameters = UtilGenerics.checkMap(context.get("requestParameters")); + if (requestParameters != null) { + String collapsedParam = (String) requestParameters.get(preferenceKey); + collapsed = "true".equals(collapsedParam); + } + } + try { + screenStringRenderer.renderScreenletBegin(writer, context, collapsed, this); + for (ModelScreenWidget subWidget : this.subWidgets) { + screenStringRenderer.renderScreenletSubWidget(writer, context, subWidget, this); + } + screenStringRenderer.renderScreenletEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering screenlet in screen named [" + getModelScreen().getName() + "]: "; + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg + e); + } + } + + public boolean collapsible() { + return this.collapsible; + } + + //initially-collapsed status, which may be overriden by user preference + public boolean getInitiallyCollapsed(Map<String, Object> context) { + String screenletId = this.getId(context) + "_collapsed"; + Map<String, ? extends Object> userPreferences = UtilGenerics.checkMap(context.get("userPreferences")); + if (userPreferences != null && userPreferences.containsKey(screenletId)) { + return Boolean.valueOf((String)userPreferences.get(screenletId)).booleanValue() ; + } + + return "true".equals(this.initiallyCollapsed.expand(context)); + } + + public boolean saveCollapsed() { + return this.saveCollapsed; + } + public boolean padded() { + return this.padded; + } + + public String getPreferenceKey(Map<String, Object> context) { + String name = this.idExdr.expandString(context); + if (name.isEmpty()) { + name = "screenlet" + "_" + Integer.toHexString(hashCode()); + } + return name; + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public List<ModelScreenWidget> getSubWidgets() { + return subWidgets; + } + + public String getTitle(Map<String, Object> context) { + String title = this.titleExdr.expandString(context); + UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder"); + if (simpleEncoder != null) { + title = simpleEncoder.encode(title); + } + return title; + } + + public Menu getNavigationMenu() { + return this.navigationMenu; + } + + public Form getNavigationForm() { + return this.navigationForm; + } + + public Menu getTabMenu() { + return this.tabMenu; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getTitleExdr() { + return titleExdr; + } + + public boolean getCollapsible() { + return collapsible; + } + + public FlexibleStringExpander getInitiallyCollapsed() { + return initiallyCollapsed; + } + + public boolean getSaveCollapsed() { + return saveCollapsed; + } + + public boolean getPadded() { + return padded; + } + } + + public static final class HorizontalSeparator extends ModelScreenWidget { + public static final String TAG_NAME = "horizontal-separator"; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander styleExdr; + + public HorizontalSeparator(ModelScreen modelScreen, Element separatorElement) { + super(modelScreen, separatorElement); + this.idExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("id")); + this.styleExdr = FlexibleStringExpander.getInstance(separatorElement.getAttribute("style")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + screenStringRenderer.renderHorizontalSeparator(writer, context, this); + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getStyle(Map<String, Object> context) { + return this.styleExdr.expandString(context); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getStyleExdr() { + return styleExdr; + } + } + + public static final class IncludeScreen extends ModelScreenWidget { + public static final String TAG_NAME = "include-screen"; + private final FlexibleStringExpander nameExdr; + private final FlexibleStringExpander locationExdr; + private final FlexibleStringExpander shareScopeExdr; + + public IncludeScreen(ModelScreen modelScreen, Element includeScreenElement) { + super(modelScreen, includeScreenElement); + this.nameExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("name")); + this.locationExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("location")); + this.shareScopeExdr = FlexibleStringExpander.getInstance(includeScreenElement.getAttribute("share-scope")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + // if we are not sharing the scope, protect it using the MapStack + boolean protectScope = !shareScope(context); + if (protectScope) { + if (!(context instanceof MapStack<?>)) { + context = MapStack.create(context); + } + + UtilGenerics.<MapStack<String>>cast(context).push(); + + // build the widgetpath + List<String> widgetTrail = UtilGenerics.toList(context.get("_WIDGETTRAIL_")); + if (widgetTrail == null) { + widgetTrail = new LinkedList<String>(); + } + + String thisName = nameExdr.expandString(context); + widgetTrail.add(thisName); + context.put("_WIDGETTRAIL_", widgetTrail); + } + + // don't need the renderer here, will just pass this on down to another screen call; screenStringRenderer.renderContainerBegin(writer, context, this); + String name = this.getName(context); + String location = this.getLocation(context); + + if (name.isEmpty()) { + if (Debug.verboseOn()) Debug.logVerbose("In the include-screen tag the screen name was empty, ignoring include; in screen [" + getModelScreen().getName() + "]", module); + return; + } + + ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer); + + if (protectScope) { + UtilGenerics.<MapStack<String>>cast(context).pop(); + } + } + + public String getName(Map<String, Object> context) { + return this.nameExdr.expandString(context); + } + + public String getLocation(Map<String, Object> context) { + return this.locationExdr.expandString(context); + } + + public boolean shareScope(Map<String, Object> context) { + String shareScopeString = this.shareScopeExdr.expandString(context); + // defaults to false, so anything but true is false + return "true".equals(shareScopeString); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getNameExdr() { + return nameExdr; + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + + public FlexibleStringExpander getShareScopeExdr() { + return shareScopeExdr; + } + } + + public static final class DecoratorScreen extends ModelScreenWidget { + public static final String TAG_NAME = "decorator-screen"; + private final FlexibleStringExpander nameExdr; + private final FlexibleStringExpander locationExdr; + private final Map<String, ModelScreenWidget> sectionMap; + + public DecoratorScreen(ModelScreen modelScreen, Element decoratorScreenElement) { + super(modelScreen, decoratorScreenElement); + this.nameExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("name")); + this.locationExdr = FlexibleStringExpander.getInstance(decoratorScreenElement.getAttribute("location")); + Map<String, ModelScreenWidget> sectionMap = new HashMap<String, ModelScreenWidget>(); + List<? extends Element> decoratorSectionElementList = UtilXml.childElementList(decoratorScreenElement, "decorator-section"); + for (Element decoratorSectionElement: decoratorSectionElementList) { + DecoratorSection decoratorSection = new DecoratorSection(modelScreen, decoratorSectionElement); + sectionMap.put(decoratorSection.getName(), decoratorSection); + } + this.sectionMap = Collections.unmodifiableMap(sectionMap); + } + + @Override + @SuppressWarnings("unchecked") + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + // isolate the scope + if (!(context instanceof MapStack)) { + context = MapStack.create(context); + } + + MapStack contextMs = (MapStack) context; + + // create a standAloneStack, basically a "save point" for this SectionsRenderer, and make a new "screens" object just for it so it is isolated and doesn't follow the stack down + MapStack standAloneStack = contextMs.standAloneChildStack(); + standAloneStack.put("screens", new ScreenRenderer(writer, standAloneStack, screenStringRenderer)); + SectionsRenderer sections = new SectionsRenderer(this.sectionMap, standAloneStack, writer, screenStringRenderer); + + // put the sectionMap in the context, make sure it is in the sub-scope, ie after calling push on the MapStack + contextMs.push(); + context.put("sections", sections); + + String name = this.getName(context); + String location = this.getLocation(context); + + ScreenFactory.renderReferencedScreen(name, location, this, writer, context, screenStringRenderer); + + contextMs.pop(); + } + + public String getName(Map<String, Object> context) { + return this.nameExdr.expandString(context); + } + + public String getLocation(Map<String, Object> context) { + return this.locationExdr.expandString(context); + } + + public Map<String, ModelScreenWidget> getSectionMap() { + return sectionMap; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getNameExdr() { + return nameExdr; + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + + } + + public static final class DecoratorSection extends ModelScreenWidget { + public static final String TAG_NAME = "decorator-section"; + private final List<ModelScreenWidget> subWidgets; + + public DecoratorSection(ModelScreen modelScreen, Element decoratorSectionElement) { + super(modelScreen, decoratorSectionElement); + // read sub-widgets + List<? extends Element> subElementList = UtilXml.childElementList(decoratorSectionElement); + this.subWidgets = ModelScreenWidget.readSubWidgets(getModelScreen(), subElementList); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + // render sub-widgets + renderSubWidgetsString(this.subWidgets, writer, context, screenStringRenderer); + } + + public List<ModelScreenWidget> getSubWidgets() { + return subWidgets; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + } + + public static final class DecoratorSectionInclude extends ModelScreenWidget { + public static final String TAG_NAME = "decorator-section-include"; + + public DecoratorSectionInclude(ModelScreen modelScreen, Element decoratorSectionElement) { + super(modelScreen, decoratorSectionElement); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + Map<String, ? extends Object> preRenderedContent = UtilGenerics.checkMap(context.get("preRenderedContent")); + if (preRenderedContent != null && preRenderedContent.containsKey(getName())) { + try { + writer.append((String) preRenderedContent.get(getName())); + } catch (IOException e) { + String errMsg = "Error rendering pre-rendered content in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } else { + SectionsRenderer sections = (SectionsRenderer) context.get("sections"); + // for now if sections is null, just log a warning; may be permissible to make the screen for flexible + if (sections == null) { + Debug.logWarning("In decorator-section-include could not find sections object in the context, not rendering section with name [" + getName() + "]", module); + } else { + sections.render(getName()); + } + } + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + } + + public static final class Label extends ModelScreenWidget { + public static final String TAG_NAME = "label"; + private final FlexibleStringExpander textExdr; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander styleExdr; + + public Label(ModelScreen modelScreen, Element labelElement) { + super(modelScreen, labelElement); + + // put the text attribute first, then the pcdata under the element, if both are there of course + String textAttr = labelElement.getAttribute("text"); + String pcdata = UtilXml.elementValue(labelElement); + if (pcdata == null) { + pcdata = ""; + } + this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata); + + this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id")); + this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + try { + screenStringRenderer.renderLabel(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering label in screen named [" + getModelScreen().getName() + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + 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 String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getStyle(Map<String, Object> context) { + return this.styleExdr.expandString(context); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getTextExdr() { + return textExdr; + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getStyleExdr() { + return styleExdr; + } + } + + public static final class Form extends ModelScreenWidget { + public static final String TAG_NAME = "include-form"; + private final FlexibleStringExpander nameExdr; + private final FlexibleStringExpander locationExdr; + private final FlexibleStringExpander shareScopeExdr; + + public Form(ModelScreen modelScreen, Element formElement) { + super(modelScreen, formElement); + this.nameExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("name")); + this.locationExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("location")); + this.shareScopeExdr = FlexibleStringExpander.getInstance(formElement.getAttribute("share-scope")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + // Output format might not support forms, so make form rendering optional. + FormStringRenderer formStringRenderer = (FormStringRenderer) context.get("formStringRenderer"); + if (formStringRenderer == null) { + Debug.logVerbose("FormStringRenderer instance not found in rendering context, form not rendered.", module); + return; + } + boolean protectScope = !shareScope(context); + if (protectScope) { + if (!(context instanceof MapStack<?>)) { + context = MapStack.create(context); + } + UtilGenerics.<MapStack<String>>cast(context).push(); + } + ModelForm modelForm = getModelForm(context); + FormRenderer renderer = new FormRenderer(modelForm, formStringRenderer); + try { + renderer.render(writer, context); + } catch (Exception e) { + String errMsg = "Error rendering included form named [" + getName() + "] at location [" + this.getLocation(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg + e); + } + + if (protectScope) { + UtilGenerics.<MapStack<String>>cast(context).pop(); + } + } + + public ModelForm getModelForm(Map<String, Object> context) { + ModelForm modelForm = null; + String name = this.getName(context); + String location = this.getLocation(context); + try { + modelForm = FormFactory.getFormFromLocation(location, name, getModelScreen().getDelegator(context).getModelReader(), getModelScreen().getDispatcher(context).getDispatchContext()); + } catch (Exception e) { + String errMsg = "Error rendering included form named [" + name + "] at location [" + location + "]: "; + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg + e); + } + return modelForm; + } + + public String getName(Map<String, Object> context) { + return this.nameExdr.expandString(context); + } + + public String getLocation() { + return locationExdr.getOriginal(); + } + + public String getLocation(Map<String, Object> context) { + return this.locationExdr.expandString(context); + } + + public boolean shareScope(Map<String, Object> context) { + String shareScopeString = this.shareScopeExdr.expandString(context); + // defaults to false, so anything but true is false + return "true".equals(shareScopeString); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getNameExdr() { + return nameExdr; + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + + public FlexibleStringExpander getShareScopeExdr() { + return shareScopeExdr; + } + + } + + public static final class Tree extends ModelScreenWidget { + public static final String TAG_NAME = "include-tree"; + private final FlexibleStringExpander nameExdr; + private final FlexibleStringExpander locationExdr; + private final FlexibleStringExpander shareScopeExdr; + + public Tree(ModelScreen modelScreen, Element treeElement) { + super(modelScreen, treeElement); + this.nameExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("name")); + this.locationExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("location")); + this.shareScopeExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("share-scope")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + // Output format might not support trees, so make tree rendering optional. + TreeStringRenderer treeStringRenderer = (TreeStringRenderer) context.get("treeStringRenderer"); + if (treeStringRenderer == null) { + Debug.logVerbose("TreeStringRenderer instance not found in rendering context, tree not rendered.", module); + return; + } + boolean protectScope = !shareScope(context); + if (protectScope) { + if (!(context instanceof MapStack<?>)) { + context = MapStack.create(context); + } + UtilGenerics.<MapStack<String>>cast(context).push(); + } + + String name = this.getName(context); + String location = this.getLocation(context); + ModelTree modelTree = null; + try { + modelTree = TreeFactory.getTreeFromLocation(this.getLocation(context), this.getName(context), getModelScreen().getDelegator(context), getModelScreen().getDispatcher(context)); + } catch (IOException e) { + String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } catch (SAXException e) { + String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } catch (ParserConfigurationException e) { + String errMsg = "Error rendering included tree named [" + name + "] at location [" + location + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + modelTree.renderTreeString(writer, context, treeStringRenderer); + if (protectScope) { + UtilGenerics.<MapStack<String>>cast(context).pop(); + } + } + + public String getName(Map<String, Object> context) { + return this.nameExdr.expandString(context); + } + + public String getLocation(Map<String, Object> context) { + return this.locationExdr.expandString(context); + } + + public boolean shareScope(Map<String, Object> context) { + String shareScopeString = this.shareScopeExdr.expandString(context); + // defaults to false, so anything but true is false + return "true".equals(shareScopeString); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + + public FlexibleStringExpander getShareScopeExdr() { + return shareScopeExdr; + } + } + + public static final class PlatformSpecific extends ModelScreenWidget { + public static final String TAG_NAME = "platform-specific"; + private final Map<String, ModelScreenWidget> subWidgets; + + public PlatformSpecific(ModelScreen modelScreen, Element platformSpecificElement) { + super(modelScreen, platformSpecificElement); + Map<String, ModelScreenWidget> subWidgets = new HashMap<String, ModelScreenWidget>(); + List<? extends Element> childElements = UtilXml.childElementList(platformSpecificElement); + if (childElements != null) { + for (Element childElement: childElements) { + if ("html".equals(childElement.getNodeName())) { + subWidgets.put("html", new HtmlWidget(modelScreen, childElement)); + } else if ("xsl-fo".equals(childElement.getNodeName())) { + subWidgets.put("xsl-fo", new HtmlWidget(modelScreen, childElement)); + } else if ("xml".equals(childElement.getNodeName())) { + subWidgets.put("xml", new HtmlWidget(modelScreen, childElement)); + } else { + throw new IllegalArgumentException("Tag not supported under the platform-specific tag with name: " + childElement.getNodeName()); + } + } + } + this.subWidgets = Collections.unmodifiableMap(subWidgets); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + ModelScreenWidget subWidget = null; + subWidget = subWidgets.get(screenStringRenderer.getRendererName()); + if (subWidget == null) { + // This is here for backward compatibility + Debug.logWarning("In platform-dependent could not find template for " + screenStringRenderer.getRendererName() + ", using the one for html.", module); + subWidget = subWidgets.get("html"); + } + if (subWidget != null) { + subWidget.renderWidgetString(writer, context, screenStringRenderer); + } + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public Map<String, ModelScreenWidget> getSubWidgets() { + return subWidgets; + } + } + + public static final class Content extends ModelScreenWidget { + public static final String TAG_NAME = "content"; + + private final FlexibleStringExpander contentId; + private final FlexibleStringExpander editRequest; + private final FlexibleStringExpander editContainerStyle; + private final FlexibleStringExpander enableEditName; + private final boolean xmlEscape; + private final FlexibleStringExpander dataResourceId; + private final String width; + private final String height; + private final String border; + + public Content(ModelScreen modelScreen, Element subContentElement) { + super(modelScreen, subContentElement); + this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id")); + this.dataResourceId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("dataresource-id")); + this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request")); + this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style")); + this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name")); + this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape")); + String width = subContentElement.getAttribute("width"); + if (width.isEmpty()) + width = "60%"; + this.height = subContentElement.getAttribute("height"); + if (this.height.isEmpty()) + width = "400px"; + this.width = width; + this.border = subContentElement.getAttribute("border"); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + try { + // pushing the contentId on the context as "contentId" is done + // because many times there will be embedded "subcontent" elements + // that use the syntax: <subcontent content-id="${contentId}"... + // and this is a step to make sure that it is there. + Delegator delegator = (Delegator) context.get("delegator"); + GenericValue content = null; + String expandedDataResourceId = getDataResourceId(context); + String expandedContentId = getContentId(context); + if (!(context instanceof MapStack<?>)) { + context = MapStack.create(context); + } + + // This is an important step to make sure that the current contentId is in the context + // as templates that contain "subcontent" elements will expect to find the master + // contentId in the context as "contentId". + UtilGenerics.<MapStack<String>>cast(context).push(); + context.put("contentId", expandedContentId); + + if (expandedDataResourceId.isEmpty()) { + if (!expandedContentId.isEmpty()) { + content = EntityQuery.use(delegator).from("Content").where("contentId", expandedContentId).cache().queryOne(); + } else { + String errMsg = "contentId is empty."; + Debug.logError(errMsg, module); + return; + } + if (content != null) { + expandedDataResourceId = content.getString("dataResourceId"); + } else { + String errMsg = "Could not find content with contentId [" + expandedContentId + "] "; + Debug.logError(errMsg, module); + throw new RuntimeException(errMsg); + } + } + + GenericValue dataResource = null; + if (!expandedDataResourceId.isEmpty()) { + dataResource = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", expandedDataResourceId).cache().queryOne(); + } + + String mimeTypeId = null; + if (dataResource != null) { + mimeTypeId = dataResource.getString("mimeTypeId"); + } + if (content != null) { + mimeTypeId = content.getString("mimeTypeId"); + } + + if (!(mimeTypeId != null + && ((mimeTypeId.indexOf("application") >= 0) || (mimeTypeId.indexOf("image")) >= 0))) { + screenStringRenderer.renderContentBegin(writer, context, this); + screenStringRenderer.renderContentBody(writer, context, this); + screenStringRenderer.renderContentEnd(writer, context, this); + } + UtilGenerics.<MapStack<String>>cast(context).pop(); + } catch (IOException e) { + String errMsg = "Error rendering content with contentId [" + getContentId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } catch (GenericEntityException e) { + String errMsg = "Error obtaining content with contentId [" + getContentId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + + } + + public String getContentId(Map<String, Object> context) { + return this.contentId.expandString(context); + } + + public String getDataResourceId() { + return this.dataResourceId.getOriginal(); + } + + public String getDataResourceId(Map<String, Object> context) { + return this.dataResourceId.expandString(context); + } + + public String getEditRequest(Map<String, Object> context) { + return this.editRequest.expandString(context); + } + + public String getEditContainerStyle(Map<String, Object> context) { + return this.editContainerStyle.expandString(context); + } + + public String getEnableEditName(Map<String, Object> context) { + return this.enableEditName.expandString(context); + } + + public boolean xmlEscape() { + return this.xmlEscape; + } + + public String getWidth() { + return this.width; + } + + public String getHeight() { + return this.height; + } + + public String getBorder() { + return this.border; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getContentId() { + return contentId; + } + + public FlexibleStringExpander getEditRequest() { + return editRequest; + } + + public FlexibleStringExpander getEditContainerStyle() { + return editContainerStyle; + } + + public FlexibleStringExpander getEnableEditName() { + return enableEditName; + } + } + + public static final class SubContent extends ModelScreenWidget { + public static final String TAG_NAME = "sub-content"; + private final FlexibleStringExpander contentId; + private final FlexibleStringExpander mapKey; + private final FlexibleStringExpander editRequest; + private final FlexibleStringExpander editContainerStyle; + private final FlexibleStringExpander enableEditName; + private final boolean xmlEscape; + + public SubContent(ModelScreen modelScreen, Element subContentElement) { + super(modelScreen, subContentElement); + this.contentId = FlexibleStringExpander.getInstance(subContentElement.getAttribute("content-id")); + String mapKey = subContentElement.getAttribute("map-key"); + if (mapKey.isEmpty()) { + mapKey = subContentElement.getAttribute("assoc-name"); + } + this.mapKey = FlexibleStringExpander.getInstance(mapKey); + this.editRequest = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-request")); + this.editContainerStyle = FlexibleStringExpander.getInstance(subContentElement.getAttribute("edit-container-style")); + this.enableEditName = FlexibleStringExpander.getInstance(subContentElement.getAttribute("enable-edit-name")); + this.xmlEscape = "true".equals(subContentElement.getAttribute("xml-escape")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + try { + screenStringRenderer.renderSubContentBegin(writer, context, this); + screenStringRenderer.renderSubContentBody(writer, context, this); + screenStringRenderer.renderSubContentEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering subContent with contentId [" + getContentId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + public String getContentId(Map<String, Object> context) { + return this.contentId.expandString(context); + } + + public String getMapKey(Map<String, Object> context) { + return this.mapKey.expandString(context); + } + + public String getEditRequest(Map<String, Object> context) { + return this.editRequest.expandString(context); + } + + public String getEditContainerStyle(Map<String, Object> context) { + return this.editContainerStyle.expandString(context); + } + + public String getEnableEditName(Map<String, Object> context) { + return this.enableEditName.expandString(context); + } + + public boolean xmlEscape() { + return this.xmlEscape; + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + // TODO Auto-generated method stub + + } + } + + public static final class Menu extends ModelScreenWidget { + public static final String TAG_NAME = "include-menu"; + private final FlexibleStringExpander nameExdr; + private final FlexibleStringExpander locationExdr; + + public Menu(ModelScreen modelScreen, Element menuElement) { + super(modelScreen, menuElement); + this.nameExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("name")); + this.locationExdr = FlexibleStringExpander.getInstance(menuElement.getAttribute("location")); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws IOException { + // Output format might not support menus, so make menu rendering optional. + MenuStringRenderer menuStringRenderer = (MenuStringRenderer) context.get("menuStringRenderer"); + if (menuStringRenderer == null) { + Debug.logVerbose("MenuStringRenderer instance not found in rendering context, menu not rendered.", module); + return; + } + ModelMenu modelMenu = getModelMenu(context); + modelMenu.renderMenuString(writer, context, menuStringRenderer); + } + + public ModelMenu getModelMenu(Map<String, Object> context) { + String name = this.getName(context); + String location = this.getLocation(context); + ModelMenu modelMenu = null; + try { + modelMenu = MenuFactory.getMenuFromLocation(location, name); + } catch (Exception e) { + String errMsg = "Error rendering included menu named [" + name + "] at location [" + location + "]: "; + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg + e); + } + return modelMenu; + } + + public String getName(Map<String, Object> context) { + return this.nameExdr.expandString(context); + } + + public String getLocation(Map<String, Object> context) { + return this.locationExdr.expandString(context); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getLocationExdr() { + return locationExdr; + } + } + + public static final class ScreenLink extends ModelScreenWidget { + public static final String TAG_NAME = "link"; + private final Link link; + private final ScreenImage image; + + public ScreenLink(ModelScreen modelScreen, Element linkElement) { + super(modelScreen, linkElement); + this.link = new Link(linkElement); + Element imageElement = UtilXml.firstChildElement(linkElement, "image"); + if (imageElement != null) { + this.image = new ScreenImage(modelScreen, imageElement); + } else { + this.image = null; + } + } + + public String getName() { + return link.getName(); + } + + public String getText(Map<String, Object> context) { + return link.getText(context); + } + + public String getId(Map<String, Object> context) { + return link.getId(context); + } + + public String getStyle(Map<String, Object> context) { + return link.getStyle(context); + } + + public String getTarget(Map<String, Object> context) { + return link.getTarget(context); + } + + public String getName(Map<String, Object> context) { + return link.getName(context); + } + + public String getTargetWindow(Map<String, Object> context) { + return link.getTargetWindow(context); + } + + public String getUrlMode() { + return link.getUrlMode(); + } + + public String getPrefix(Map<String, Object> context) { + return link.getPrefix(context); + } + + public boolean getFullPath() { + return link.getFullPath(); + } + + public boolean getSecure() { + return link.getSecure(); + } + + public boolean getEncode() { + return link.getEncode(); + } + + public ScreenImage getImage() { + return image; + } + + public String getLinkType() { + return link.getLinkType(); + } + + public String getWidth() { + return link.getWidth(); + } + + public String getHeight() { + return link.getHeight(); + } + + public Map<String, String> getParameterMap(Map<String, Object> context) { + return link.getParameterMap(context); + } + + public FlexibleStringExpander getTextExdr() { + return link.getTextExdr(); + } + + public FlexibleStringExpander getIdExdr() { + return link.getIdExdr(); + } + + public FlexibleStringExpander getStyleExdr() { + return link.getStyleExdr(); + } + + public FlexibleStringExpander getTargetExdr() { + return link.getTargetExdr(); + } + + public FlexibleStringExpander getTargetWindowExdr() { + return link.getTargetWindowExdr(); + } + + public FlexibleStringExpander getPrefixExdr() { + return link.getPrefixExdr(); + } + + public FlexibleStringExpander getNameExdr() { + return link.getNameExdr(); + } + + public List<Parameter> getParameterList() { + return link.getParameterList(); + } + + public AutoServiceParameters getAutoServiceParameters() { + return link.getAutoServiceParameters(); + } + + public AutoEntityParameters getAutoEntityParameters() { + return link.getAutoEntityParameters(); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + try { + screenStringRenderer.renderLink(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering link with id [" + link.getId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public Link getLink() { + return link; + } + } + + public static final class ScreenImage extends ModelScreenWidget { + public static final String TAG_NAME = "image"; + private final Image image; + + public String getName() { + return image.getName(); + } + + public String getSrc(Map<String, Object> context) { + return image.getSrc(context); + } + + public String getId(Map<String, Object> context) { + return image.getId(context); + } + + public String getStyle(Map<String, Object> context) { + return image.getStyle(context); + } + + public String getWidth(Map<String, Object> context) { + return image.getWidth(context); + } + + public String getHeight(Map<String, Object> context) { + return image.getHeight(context); + } + + public String getBorder(Map<String, Object> context) { + return image.getBorder(context); + } + + public String getAlt(Map<String, Object> context) { + return image.getAlt(context); + } + + public String getUrlMode() { + return image.getUrlMode(); + } + + public FlexibleStringExpander getSrcExdr() { + return image.getSrcExdr(); + } + + public FlexibleStringExpander getIdExdr() { + return image.getIdExdr(); + } + + public FlexibleStringExpander getStyleExdr() { + return image.getStyleExdr(); + } + + public FlexibleStringExpander getWidthExdr() { + return image.getWidthExdr(); + } + + public FlexibleStringExpander getHeightExdr() { + return image.getHeightExdr(); + } + + public FlexibleStringExpander getBorderExdr() { + return image.getBorderExdr(); + } + + public FlexibleStringExpander getAlt() { + return image.getAlt(); + } + + public ScreenImage(ModelScreen modelScreen, Element imageElement) { + super(modelScreen, imageElement); + this.image = new Image(imageElement); + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) { + try { + screenStringRenderer.renderImage(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering image with id [" + image.getId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public Image getImage() { + return image; + } + } + + public static final class PortalPage extends ModelScreenWidget { + public static final String TAG_NAME = "include-portal-page"; + private final FlexibleStringExpander idExdr; + private final FlexibleStringExpander confModeExdr; + private final Boolean usePrivate; + + public PortalPage(ModelScreen modelScreen, Element portalPageElement) { + super(modelScreen, portalPageElement); + this.idExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("id")); + this.confModeExdr = FlexibleStringExpander.getInstance(portalPageElement.getAttribute("conf-mode")); + this.usePrivate = !("false".equals(portalPageElement.getAttribute("use-private"))); + } + + private GenericValue getPortalPageValue(Map<String, Object> context) { + Delegator delegator = (Delegator) context.get("delegator"); + String expandedPortalPageId = getId(context); + GenericValue portalPage = null; + if (!expandedPortalPageId.isEmpty()) { + if (usePrivate) { + portalPage = PortalPageWorker.getPortalPage(expandedPortalPageId, context); + } else { + try { + portalPage = EntityQuery.use(delegator) + .from("PortalPage") + .where("portalPageId", expandedPortalPageId) + .cache().queryOne(); + } catch (GenericEntityException e) { + throw new RuntimeException(e); + } + } + } + if (portalPage == null) { + String errMsg = "Could not find PortalPage with portalPageId [" + expandedPortalPageId + "] "; + Debug.logError(errMsg, module); + throw new RuntimeException(errMsg); + } + return portalPage; + } + + @Override + public void renderWidgetString(Appendable writer, Map<String, Object> context, ScreenStringRenderer screenStringRenderer) throws GeneralException, IOException { + try { + Delegator delegator = (Delegator) context.get("delegator"); + List<GenericValue> portalPageColumns = null; + List<GenericValue> portalPagePortlets = null; + List<GenericValue> portletAttributes = null; + GenericValue portalPage = getPortalPageValue(context); + String actualPortalPageId = portalPage.getString("portalPageId"); + portalPageColumns = EntityQuery.use(delegator) + .from("PortalPageColumn") + .where("portalPageId", actualPortalPageId) + .orderBy("columnSeqId") + .cache(true) + .queryList(); + + // Renders the portalPage header + screenStringRenderer.renderPortalPageBegin(writer, context, this); + + // First column has no previous column + String prevColumnSeqId = ""; + + // Iterates through the PortalPage columns + ListIterator <GenericValue>columnsIterator = portalPageColumns.listIterator(); + while(columnsIterator.hasNext()) { + GenericValue columnValue = columnsIterator.next(); + String columnSeqId = columnValue.getString("columnSeqId"); + + // Renders the portalPageColumn header + screenStringRenderer.renderPortalPageColumnBegin(writer, context, this, columnValue); + + // Get the Portlets located in the current column + portalPagePortlets = EntityQuery.use(delegator) + .from("PortalPagePortletView") + .where("portalPageId", portalPage.getString("portalPageId"), "columnSeqId", columnSeqId) + .orderBy("sequenceNum") + .queryList(); + // First Portlet in a Column has no previous Portlet + String prevPortletId = ""; + String prevPortletSeqId = ""; + + // If this is not the last column, get the next columnSeqId + String nextColumnSeqId = ""; + if (columnsIterator.hasNext()) { + nextColumnSeqId = portalPageColumns.get(columnsIterator.nextIndex()).getString("columnSeqId"); + } + + // Iterates through the Portlets in the Column + ListIterator <GenericValue>portletsIterator = portalPagePortlets.listIterator(); + while(portletsIterator.hasNext()) { + GenericValue portletValue = portletsIterator.next(); + + // If not the last portlet in the column, get the next nextPortletId and nextPortletSeqId + String nextPortletId = ""; + String nextPortletSeqId = ""; + if (portletsIterator.hasNext()) { + nextPortletId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portalPortletId"); + nextPortletSeqId = portalPagePortlets.get(portletsIterator.nextIndex()).getString("portletSeqId"); + } + + // Set info to allow portlet movement in the page + context.put("prevPortletId", prevPortletId); + context.put("prevPortletSeqId", prevPortletSeqId); + context.put("nextPortletId", nextPortletId); + context.put("nextPortletSeqId", nextPortletSeqId); + context.put("prevColumnSeqId", prevColumnSeqId); + context.put("nextColumnSeqId", nextColumnSeqId); + + // Get portlet's attributes + portletAttributes = EntityQuery.use(delegator) + .from("PortletAttribute") + .where("portalPageId", portletValue.get("portalPageId"), "portalPortletId", portletValue.get("portalPortletId"), "portletSeqId", portletValue.get("portletSeqId")) + .queryList(); + + ListIterator <GenericValue>attributesIterator = portletAttributes.listIterator(); + while (attributesIterator.hasNext()) { + GenericValue attribute = attributesIterator.next(); + context.put(attribute.getString("attrName"), attribute.getString("attrValue")); + } + + // Renders the portalPagePortlet + screenStringRenderer.renderPortalPagePortletBegin(writer, context, this, portletValue); + screenStringRenderer.renderPortalPagePortletBody(writer, context, this, portletValue); + screenStringRenderer.renderPortalPagePortletEnd(writer, context, this, portletValue); + + // Remove the portlet's attributes so that these are not available for other portlets + while (attributesIterator.hasPrevious()) { + GenericValue attribute = attributesIterator.previous(); + context.remove(attribute.getString("attrName")); + } + + // Uses the actual portlet as prevPortlet for next iteration + prevPortletId = (String) portletValue.get("portalPortletId"); + prevPortletSeqId = (String) portletValue.get("portletSeqId"); + } + // Renders the portalPageColumn footer + screenStringRenderer.renderPortalPageColumnEnd(writer, context, this, columnValue); + + // Uses the actual columnSeqId as prevColumnSeqId for next iteration + prevColumnSeqId = columnSeqId; + } + // Renders the portalPage footer + screenStringRenderer.renderPortalPageEnd(writer, context, this); + } catch (IOException e) { + String errMsg = "Error rendering PortalPage with portalPageId [" + getId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } catch (GenericEntityException e) { + String errMsg = "Error obtaining PortalPage with portalPageId [" + getId(context) + "]: " + e.toString(); + Debug.logError(e, errMsg, module); + throw new RuntimeException(errMsg); + } + } + + public String getId(Map<String, Object> context) { + return this.idExdr.expandString(context); + } + + public String getOriginalPortalPageId(Map<String, Object> context) { + GenericValue portalPage = getPortalPageValue(context); + return portalPage.getString("originalPortalPageId"); + } + + public String getActualPortalPageId(Map<String, Object> context) { + GenericValue portalPage = getPortalPageValue(context); + return portalPage.getString("portalPageId"); + } + + public String getConfMode(Map<String, Object> context) { + return this.confModeExdr.expandString(context); + } + + public String getUsePrivate() { + return Boolean.toString(this.usePrivate); + } + + @Override + public void accept(ModelWidgetVisitor visitor) throws Exception { + visitor.visit(this); + } + + public FlexibleStringExpander getIdExdr() { + return idExdr; + } + + public FlexibleStringExpander getConfModeExdr() { + return confModeExdr; + } + } + +} |
Free forum by Nabble | Edit this page |