/******************************************************************************* | |
* 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.Collections; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.ListIterator; | |
import java.util.Map; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.xml.parsers.ParserConfigurationException; | |
import org.ofbiz.base.util.Debug; | |
import org.ofbiz.base.util.GeneralException; | |
import org.ofbiz.base.util.StringUtil; | |
import org.ofbiz.base.util.UtilCodec; | |
import org.ofbiz.base.util.UtilGenerics; | |
import org.ofbiz.base.util.UtilHttp; | |
import org.ofbiz.base.util.UtilValidate; | |
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.model.ModelEntity; | |
import org.ofbiz.entity.model.ModelField; | |
import org.ofbiz.entity.util.EntityListIterator; | |
import org.ofbiz.entity.util.EntityQuery; | |
import org.ofbiz.widget.WidgetWorker; | |
import org.ofbiz.widget.model.CommonWidgetModels.Parameter; | |
import org.ofbiz.widget.renderer.ScreenRenderException; | |
import org.ofbiz.widget.renderer.ScreenStringRenderer; | |
import org.ofbiz.widget.renderer.TreeStringRenderer; | |
import org.w3c.dom.Element; | |
import org.xml.sax.SAXException; | |
/** | |
* Models the <tree> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
@SuppressWarnings("serial") | |
public class ModelTree extends ModelWidget { | |
/* | |
* ----------------------------------------------------------------------- * | |
* 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 = ModelTree.class.getName(); | |
private final String defaultEntityName; | |
private final String defaultRenderStyle; | |
private final FlexibleStringExpander defaultWrapStyleExdr; | |
private final FlexibleStringExpander expandCollapseRequestExdr; | |
private final boolean forceChildCheck; | |
private final String location; | |
private final Map<String, ModelNode> nodeMap; | |
private final int openDepth; | |
private final int postTrailOpenDepth; | |
private final String rootNodeName; | |
private final FlexibleStringExpander trailNameExdr; | |
public ModelTree(Element treeElement, String location) { | |
super(treeElement); | |
this.location = location; | |
this.rootNodeName = treeElement.getAttribute("root-node-name"); | |
String defaultRenderStyle = UtilXml.checkEmpty(treeElement.getAttribute("default-render-style"), "simple"); | |
// A temporary hack to accommodate those who might still be using "render-style" instead of "default-render-style" | |
if (defaultRenderStyle.isEmpty() || defaultRenderStyle.equals("simple")) { | |
String rStyle = treeElement.getAttribute("render-style"); | |
if (!rStyle.isEmpty()) | |
defaultRenderStyle = rStyle; | |
} | |
this.defaultRenderStyle = defaultRenderStyle; | |
this.defaultWrapStyleExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("default-wrap-style")); | |
this.expandCollapseRequestExdr = FlexibleStringExpander.getInstance(treeElement.getAttribute("expand-collapse-request")); | |
this.trailNameExdr = FlexibleStringExpander.getInstance(UtilXml.checkEmpty(treeElement.getAttribute("trail-name"), | |
"trail")); | |
this.forceChildCheck = !"false".equals(treeElement.getAttribute("force-child-check")); | |
this.defaultEntityName = treeElement.getAttribute("entity-name"); | |
int openDepth = 0; | |
if (treeElement.hasAttribute("open-depth")) { | |
try { | |
openDepth = Integer.parseInt(treeElement.getAttribute("open-depth")); | |
} catch (NumberFormatException e) { | |
throw new IllegalArgumentException("Invalid open-depth attribute value for the tree definition with name: " | |
+ getName()); | |
} | |
} | |
this.openDepth = openDepth; | |
int postTrailOpenDepth = 999; | |
if (treeElement.hasAttribute("post-trail-open-depth")) { | |
try { | |
postTrailOpenDepth = Integer.parseInt(treeElement.getAttribute("post-trail-open-depth")); | |
} catch (NumberFormatException e) { | |
throw new IllegalArgumentException( | |
"Invalid post-trail-open-depth attribute value for the tree definition with name: " + getName()); | |
} | |
} | |
this.postTrailOpenDepth = postTrailOpenDepth; | |
List<? extends Element> nodeElements = UtilXml.childElementList(treeElement, "node"); | |
if (nodeElements.size() == 0) { | |
throw new IllegalArgumentException("No node elements found for the tree definition with name: " + getName()); | |
} | |
Map<String, ModelNode> nodeMap = new HashMap<String, ModelNode>(); | |
for (Element nodeElementEntry : UtilXml.childElementList(treeElement, "node")) { | |
ModelNode node = new ModelNode(nodeElementEntry, this); | |
String nodeName = node.getName(); | |
nodeMap.put(nodeName, node); | |
} | |
this.nodeMap = Collections.unmodifiableMap(nodeMap); | |
} | |
@Override | |
public void accept(ModelWidgetVisitor visitor) throws Exception { | |
visitor.visit(this); | |
} | |
@Override | |
public String getBoundaryCommentName() { | |
return location + "#" + getName(); | |
} | |
public String getDefaultEntityName() { | |
return this.defaultEntityName; | |
} | |
public String getDefaultPkName(Map<String, Object> context) { | |
ModelEntity modelEntity = WidgetWorker.getDelegator(context).getModelEntity(this.defaultEntityName); | |
if (modelEntity.getPksSize() == 1) { | |
ModelField modelField = modelEntity.getOnlyPk(); | |
return modelField.getName(); | |
} | |
return null; | |
} | |
public String getExpandCollapseRequest(Map<String, Object> context) { | |
String expColReq = this.expandCollapseRequestExdr.expandString(context); | |
if (UtilValidate.isEmpty(expColReq)) { | |
HttpServletRequest request = (HttpServletRequest) context.get("request"); | |
String s1 = request.getRequestURI(); | |
int pos = s1.lastIndexOf("/"); | |
if (pos >= 0) | |
expColReq = s1.substring(pos + 1); | |
else | |
expColReq = s1; | |
} | |
//append also the request parameters | |
Map<String, Object> paramMap = UtilGenerics.checkMap(context.get("requestParameters")); | |
if (UtilValidate.isNotEmpty(paramMap)) { | |
Map<String, Object> requestParameters = new HashMap<String, Object>(paramMap); | |
requestParameters.remove(this.getTrailName(context)); | |
if (UtilValidate.isNotEmpty(requestParameters)) { | |
String queryString = UtilHttp.urlEncodeArgs(requestParameters, false); | |
if (expColReq.indexOf("?") < 0) { | |
expColReq += "?"; | |
} else { | |
expColReq += "&"; | |
} | |
expColReq += queryString; | |
} | |
} | |
return expColReq; | |
} | |
public int getOpenDepth() { | |
return openDepth; | |
} | |
public int getPostTrailOpenDepth() { | |
return postTrailOpenDepth; | |
} | |
public String getRenderStyle() { | |
return this.defaultRenderStyle; | |
} | |
public String getRootNodeName() { | |
return rootNodeName; | |
} | |
public String getTrailName(Map<String, Object> context) { | |
return this.trailNameExdr.expandString(context); | |
} | |
public String getWrapStyle(Map<String, Object> context) { | |
return this.defaultWrapStyleExdr.expandString(context); | |
} | |
/** | |
* Renders this model. | |
* | |
* @param writer | |
* @param context | |
* @param treeStringRenderer | |
*/ | |
@SuppressWarnings("rawtypes") | |
public void renderTreeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) | |
throws GeneralException { | |
Map<String, Object> parameters = UtilGenerics.checkMap(context.get("parameters")); | |
ModelNode node = nodeMap.get(rootNodeName); | |
String trailName = trailNameExdr.expandString(context); | |
String treeString = (String) context.get(trailName); | |
if (UtilValidate.isEmpty(treeString)) { | |
treeString = (String) parameters.get(trailName); | |
} | |
List<String> trail = null; | |
if (UtilValidate.isNotEmpty(treeString)) { | |
trail = StringUtil.split(treeString, "|"); | |
if (UtilValidate.isEmpty(trail)) | |
throw new RuntimeException("Tree 'trail' value is empty."); | |
context.put("rootEntityId", trail.get(0)); | |
context.put(getDefaultPkName(context), trail.get(0)); | |
} else { | |
trail = new LinkedList<String>(); | |
} | |
context.put("targetNodeTrail", trail); | |
context.put("currentNodeTrail", new LinkedList()); | |
try { | |
node.renderNodeString(writer, context, treeStringRenderer, 0); | |
} catch (IOException e2) { | |
String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString(); | |
Debug.logError(e2, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} | |
} | |
public String getDefaultRenderStyle() { | |
return defaultRenderStyle; | |
} | |
public FlexibleStringExpander getDefaultWrapStyleExdr() { | |
return defaultWrapStyleExdr; | |
} | |
public FlexibleStringExpander getExpandCollapseRequestExdr() { | |
return expandCollapseRequestExdr; | |
} | |
public boolean getForceChildCheck() { | |
return forceChildCheck; | |
} | |
public String getLocation() { | |
return location; | |
} | |
public Map<String, ModelNode> getNodeMap() { | |
return nodeMap; | |
} | |
public FlexibleStringExpander getTrailNameExdr() { | |
return trailNameExdr; | |
} | |
/** | |
* Models the <node> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
public static class ModelNode extends ModelWidget { | |
private final List<ModelAction> actions; | |
// TODO: Make this a generic condition object. | |
private final ModelTreeCondition condition; | |
private final String entityName; | |
private final String entryName; | |
private final String expandCollapseStyle; | |
private final Label label; | |
private final Link link; | |
private final ModelTree modelTree; | |
private final String pkName; | |
private final String renderStyle; | |
private final FlexibleStringExpander screenLocationExdr; | |
private final FlexibleStringExpander screenNameExdr; | |
private final String shareScope; | |
private final List<ModelSubNode> subNodeList; | |
private final FlexibleStringExpander wrapStyleExdr; | |
public ModelNode(Element nodeElement, ModelTree modelTree) { | |
super(nodeElement); | |
this.modelTree = modelTree; | |
this.expandCollapseStyle = nodeElement.getAttribute("expand-collapse-style"); | |
this.wrapStyleExdr = FlexibleStringExpander.getInstance(nodeElement.getAttribute("wrap-style")); | |
this.renderStyle = nodeElement.getAttribute("render-style"); | |
this.entryName = nodeElement.getAttribute("entry-name"); | |
this.entityName = nodeElement.getAttribute("entity-name"); | |
this.pkName = nodeElement.getAttribute("join-field-name"); | |
ArrayList<ModelAction> actions = new ArrayList<ModelAction>(); | |
// FIXME: Validate child elements, should be only one of actions, entity-one, service, script. | |
Element actionsElement = UtilXml.firstChildElement(nodeElement, "actions"); | |
if (actionsElement != null) { | |
actions.addAll(ModelTreeAction.readNodeActions(this, actionsElement)); | |
} | |
Element actionElement = UtilXml.firstChildElement(nodeElement, "entity-one"); | |
if (actionElement != null) { | |
actions.add(new AbstractModelAction.EntityOne(this, actionElement)); | |
} | |
actionElement = UtilXml.firstChildElement(nodeElement, "service"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.Service(this, actionElement)); | |
} | |
actionElement = UtilXml.firstChildElement(nodeElement, "script"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.Script(this, actionElement)); | |
} | |
actions.trimToSize(); | |
this.actions = Collections.unmodifiableList(actions); | |
Element screenElement = UtilXml.firstChildElement(nodeElement, "include-screen"); | |
if (screenElement != null) { | |
this.screenNameExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("name")); | |
this.screenLocationExdr = FlexibleStringExpander.getInstance(screenElement.getAttribute("location")); | |
this.shareScope = screenElement.getAttribute("share-scope"); | |
} else { | |
this.screenNameExdr = FlexibleStringExpander.getInstance(""); | |
this.screenLocationExdr = FlexibleStringExpander.getInstance(""); | |
this.shareScope = ""; | |
} | |
Element labelElement = UtilXml.firstChildElement(nodeElement, "label"); | |
if (labelElement != null) { | |
this.label = new Label(labelElement); | |
} else { | |
this.label = null; | |
} | |
Element linkElement = UtilXml.firstChildElement(nodeElement, "link"); | |
if (linkElement != null) { | |
this.link = new Link(linkElement); | |
} else { | |
this.link = null; | |
} | |
Element conditionElement = UtilXml.firstChildElement(nodeElement, "condition"); | |
if (conditionElement != null) { | |
this.condition = new ModelTreeCondition(modelTree, conditionElement); | |
} else { | |
this.condition = null; | |
} | |
List<? extends Element> nodeElements = UtilXml.childElementList(nodeElement, "sub-node"); | |
if (!nodeElements.isEmpty()) { | |
List<ModelSubNode> subNodeList = new ArrayList<ModelSubNode>(); | |
for (Element subNodeElementEntry : nodeElements) { | |
ModelSubNode subNode = new ModelSubNode(subNodeElementEntry, this); | |
subNodeList.add(subNode); | |
} | |
this.subNodeList = Collections.unmodifiableList(subNodeList); | |
} else { | |
this.subNodeList = Collections.emptyList(); | |
} | |
} | |
@Override | |
public void accept(ModelWidgetVisitor visitor) throws Exception { | |
visitor.visit(this); | |
} | |
private List<Object[]> getChildren(Map<String, Object> context) { | |
List<Object[]> subNodeValues = new ArrayList<Object[]>(); | |
for (ModelSubNode subNode : subNodeList) { | |
String nodeName = subNode.getNodeName(context); | |
ModelNode node = modelTree.nodeMap.get(nodeName); | |
List<ModelAction> subNodeActions = subNode.getActions(); | |
//if (Debug.infoOn()) Debug.logInfo(" context.currentValue:" + context.get("currentValue"), module); | |
AbstractModelAction.runSubActions(subNodeActions, context); | |
// List dataFound = (List)context.get("dataFound"); | |
Iterator<? extends Map<String, ? extends Object>> dataIter = subNode.getListIterator(context); | |
if (dataIter instanceof EntityListIterator) { | |
EntityListIterator eli = (EntityListIterator) dataIter; | |
Map<String, Object> val = null; | |
while ((val = eli.next()) != null) { | |
Object[] arr = { node, val }; | |
subNodeValues.add(arr); | |
} | |
try { | |
eli.close(); | |
} catch (GenericEntityException e) { | |
Debug.logError(e, module); | |
throw new RuntimeException(e.getMessage()); | |
} | |
} else if (dataIter != null) { | |
while (dataIter.hasNext()) { | |
Map<String, ? extends Object> val = dataIter.next(); | |
Object[] arr = { node, val }; | |
subNodeValues.add(arr); | |
} | |
} | |
} | |
return subNodeValues; | |
} | |
public String getEntityName() { | |
if (!this.entityName.isEmpty()) { | |
return this.entityName; | |
} else { | |
return this.modelTree.getDefaultEntityName(); | |
} | |
} | |
public String getEntryName() { | |
return this.entryName; | |
} | |
public String getExpandCollapseStyle() { | |
return expandCollapseStyle; | |
} | |
public ModelTree getModelTree() { | |
return this.modelTree; | |
} | |
public String getPkName(Map<String, Object> context) { | |
if (UtilValidate.isNotEmpty(this.pkName)) { | |
return this.pkName; | |
} else { | |
return this.modelTree.getDefaultPkName(context); | |
} | |
} | |
public String getRenderStyle() { | |
if (this.renderStyle.isEmpty()) | |
return modelTree.getRenderStyle(); | |
return this.renderStyle; | |
} | |
public String getWrapStyle(Map<String, Object> context) { | |
String val = this.wrapStyleExdr.expandString(context); | |
if (val.isEmpty()) { | |
val = this.modelTree.getWrapStyle(context); | |
} | |
return val; | |
} | |
public boolean hasChildren(Map<String, Object> context) { | |
List<Object[]> subNodeValues = getChildren(context); | |
boolean hasChildren = false; | |
Long nodeCount = null; | |
String countFieldName = "childBranchCount"; | |
Object obj = null; | |
if (!this.entryName.isEmpty()) { | |
Map<String, Object> map = UtilGenerics.cast(context.get(this.entryName)); | |
if (map instanceof GenericValue) { | |
ModelEntity modelEntity = ((GenericValue) map).getModelEntity(); | |
if (modelEntity.isField(countFieldName)) { | |
obj = map.get(countFieldName); | |
} | |
} | |
} else { | |
obj = context.get(countFieldName); | |
} | |
if (obj != null) { | |
nodeCount = (Long) obj; | |
} | |
String entName = this.getEntityName(); | |
Delegator delegator = WidgetWorker.getDelegator(context); | |
ModelEntity modelEntity = delegator.getModelEntity(entName); | |
ModelField modelField = null; | |
if (modelEntity.isField(countFieldName)) { | |
modelField = modelEntity.getField(countFieldName); | |
} | |
if (nodeCount == null && modelField != null || this.modelTree.forceChildCheck) { | |
getChildren(context); | |
/* | |
String id = (String)context.get(modelTree.getPkName()); | |
if (UtilValidate.isNotEmpty(id)) { | |
try { | |
int leafCount = ContentManagementWorker.updateStatsTopDown(delegator, id, UtilMisc.toList("SUB_CONTENT", "PUBLISH_LINK")); | |
GenericValue entity = delegator.findOne(entName, UtilMisc.toMap(modelTree.getPkName(), id), true); | |
obj = entity.get("childBranchCount"); | |
if (obj != null) | |
nodeCount = (Long)obj; | |
} catch (GenericEntityException e) { | |
Debug.logError(e, module); | |
throw new RuntimeException(e.getMessage()); | |
} | |
} | |
*/ | |
nodeCount = Long.valueOf(subNodeValues.size()); | |
String pkName = this.getPkName(context); | |
String id = null; | |
if (!this.entryName.isEmpty()) { | |
id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName); | |
} else { | |
id = (String) context.get(pkName); | |
} | |
try { | |
if (id != null && modelEntity.getPksSize() == 1) { | |
GenericValue entity = EntityQuery.use(delegator).from(entName).where(pkName, id).queryOne(); | |
if (modelEntity.isField("childBranchCount")) { | |
entity.put("childBranchCount", nodeCount); | |
entity.store(); | |
} | |
} | |
} catch (GenericEntityException e) { | |
Debug.logError(e, module); | |
throw new RuntimeException(e.getMessage()); | |
} | |
} else if (nodeCount == null) { | |
getChildren(context); | |
if (subNodeValues != null) { | |
nodeCount = Long.valueOf(subNodeValues.size()); | |
} | |
} | |
if (nodeCount != null && nodeCount.intValue() > 0) { | |
hasChildren = true; | |
} | |
return hasChildren; | |
} | |
public boolean isExpandCollapse() { | |
boolean isExpCollapse = false; | |
String rStyle = getRenderStyle(); | |
if (rStyle != null && rStyle.equals("expand-collapse")) | |
isExpCollapse = true; | |
return isExpCollapse; | |
} | |
public boolean isFollowTrail() { | |
boolean isFollowTrail = false; | |
String rStyle = getRenderStyle(); | |
if (rStyle != null && (rStyle.equals("follow-trail") || rStyle.equals("show-peers") || rStyle.equals("follow-trail"))) { | |
isFollowTrail = true; | |
} | |
return isFollowTrail; | |
} | |
public boolean isRootNode() { | |
return getName().equals(modelTree.getRootNodeName()); | |
} | |
public void renderNodeString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer, | |
int depth) throws IOException, GeneralException { | |
boolean passed = true; | |
if (this.condition != null) { | |
if (!this.condition.getCondition().eval(context)) { | |
passed = false; | |
} | |
} | |
//Debug.logInfo("in ModelMenu, name:" + this.getName(), module); | |
if (passed) { | |
List<String> currentNodeTrail = UtilGenerics.toList(context.get("currentNodeTrail")); | |
context.put("processChildren", Boolean.TRUE); | |
// this action will usually obtain the "current" entity | |
ModelTreeAction.runSubActions(this.actions, context); | |
String pkName = getPkName(context); | |
String id = null; | |
if (!this.entryName.isEmpty()) { | |
id = UtilGenerics.<Map<String, String>> cast(context.get(this.entryName)).get(pkName); | |
} else { | |
id = (String) context.get(pkName); | |
} | |
currentNodeTrail.add(id); | |
treeStringRenderer.renderNodeBegin(writer, context, this, depth); | |
//if (Debug.infoOn()) Debug.logInfo(" context:" + | |
// context.entrySet(), module); | |
try { | |
String screenName = null; | |
if (!screenNameExdr.isEmpty()) | |
screenName = screenNameExdr.expandString(context); | |
String screenLocation = null; | |
if (!screenLocationExdr.isEmpty()) | |
screenLocation = screenLocationExdr.expandString(context); | |
if (screenName != null && screenLocation != null) { | |
ScreenStringRenderer screenStringRenderer = treeStringRenderer.getScreenStringRenderer(context); | |
ModelScreen modelScreen = ScreenFactory.getScreenFromLocation(screenLocation, screenName); | |
modelScreen.renderScreenString(writer, context, screenStringRenderer); | |
} | |
if (label != null) { | |
label.renderLabelString(writer, context, treeStringRenderer); | |
} | |
if (link != null) { | |
link.renderLinkString(writer, context, treeStringRenderer); | |
} | |
treeStringRenderer.renderLastElement(writer, context, this); | |
Boolean processChildren = (Boolean) context.get("processChildren"); | |
//if (Debug.infoOn()) Debug.logInfo(" processChildren:" + processChildren, module); | |
if (processChildren.booleanValue()) { | |
List<Object[]> subNodeValues = getChildren(context); | |
int newDepth = depth + 1; | |
for (Object[] arr : subNodeValues) { | |
ModelNode node = (ModelNode) arr[0]; | |
Map<String, Object> val = UtilGenerics.checkMap(arr[1]); | |
//GenericPK pk = val.getPrimaryKey(); | |
//if (Debug.infoOn()) Debug.logInfo(" pk:" + pk, | |
// module); | |
String thisPkName = node.getPkName(context); | |
String thisEntityId = (String) val.get(thisPkName); | |
MapStack<String> newContext = MapStack.create(context); | |
newContext.push(); | |
String nodeEntryName = node.getEntryName(); | |
if (!nodeEntryName.isEmpty()) { | |
newContext.put(nodeEntryName, val); | |
} else { | |
newContext.putAll(val); | |
} | |
String targetEntityId = null; | |
List<String> targetNodeTrail = UtilGenerics.checkList(context.get("targetNodeTrail")); | |
if (newDepth < targetNodeTrail.size()) { | |
targetEntityId = targetNodeTrail.get(newDepth); | |
} | |
if ((targetEntityId != null && targetEntityId.equals(thisEntityId)) | |
|| this.showPeers(newDepth, context)) { | |
node.renderNodeString(writer, newContext, treeStringRenderer, newDepth); | |
} | |
} | |
} | |
} catch (ScreenRenderException e) { | |
String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} catch (SAXException e) { | |
String errMsg = "Error rendering included label with name [" + getName() + "] : " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} catch (ParserConfigurationException e3) { | |
String errMsg = "Error rendering included label with name [" + getName() + "] : " + e3.toString(); | |
Debug.logError(e3, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} catch (IOException e2) { | |
String errMsg = "Error rendering included label with name [" + getName() + "] : " + e2.toString(); | |
Debug.logError(e2, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} | |
treeStringRenderer.renderNodeEnd(writer, context, this); | |
int removeIdx = currentNodeTrail.size() - 1; | |
if (removeIdx >= 0) | |
currentNodeTrail.remove(removeIdx); | |
} | |
} | |
public boolean showPeers(int currentDepth, Map<String, Object> context) { | |
int trailSize = 0; | |
List<?> trail = UtilGenerics.checkList(context.get("targetNodeTrail")); | |
int openDepth = modelTree.getOpenDepth(); | |
int postTrailOpenDepth = modelTree.getPostTrailOpenDepth(); | |
if (trail != null) | |
trailSize = trail.size(); | |
boolean showPeers = false; | |
String rStyle = getRenderStyle(); | |
if (rStyle == null) { | |
showPeers = true; | |
} else if (!isFollowTrail()) { | |
showPeers = true; | |
} else if ((currentDepth < trailSize) && (rStyle != null) | |
&& (rStyle.equals("show-peers") || rStyle.equals("expand-collapse"))) { | |
showPeers = true; | |
} else if (openDepth >= currentDepth) { | |
showPeers = true; | |
} else { | |
int depthAfterTrail = currentDepth - trailSize; | |
if (depthAfterTrail >= 0 && depthAfterTrail <= postTrailOpenDepth) | |
showPeers = true; | |
} | |
return showPeers; | |
} | |
public List<ModelAction> getActions() { | |
return actions; | |
} | |
public ModelTreeCondition getCondition() { | |
return condition; | |
} | |
public Label getLabel() { | |
return label; | |
} | |
public Link getLink() { | |
return link; | |
} | |
public String getPkName() { | |
return pkName; | |
} | |
public FlexibleStringExpander getScreenLocationExdr() { | |
return screenLocationExdr; | |
} | |
public FlexibleStringExpander getScreenNameExdr() { | |
return screenNameExdr; | |
} | |
public String getShareScope() { | |
return shareScope; | |
} | |
public List<ModelSubNode> getSubNodeList() { | |
return subNodeList; | |
} | |
public FlexibleStringExpander getWrapStyleExdr() { | |
return wrapStyleExdr; | |
} | |
/** | |
* Models the <image> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
public static class Image { | |
private final FlexibleStringExpander borderExdr; | |
private final FlexibleStringExpander heightExdr; | |
private final FlexibleStringExpander idExdr; | |
private final FlexibleStringExpander srcExdr; | |
private final FlexibleStringExpander styleExdr; | |
private final String urlMode; | |
private final FlexibleStringExpander widthExdr; | |
public Image(Element imageElement) { | |
this.borderExdr = FlexibleStringExpander | |
.getInstance(UtilXml.checkEmpty(imageElement.getAttribute("border"), "0")); | |
this.heightExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("height")); | |
this.idExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("id")); | |
this.srcExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("src")); | |
this.styleExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("style")); | |
this.urlMode = UtilXml.checkEmpty(imageElement.getAttribute("url-mode"), "content"); | |
this.widthExdr = FlexibleStringExpander.getInstance(imageElement.getAttribute("width")); | |
} | |
public String getBorder(Map<String, Object> context) { | |
return this.borderExdr.expandString(context); | |
} | |
public String getHeight(Map<String, Object> context) { | |
return this.heightExdr.expandString(context); | |
} | |
public String getId(Map<String, Object> context) { | |
return this.idExdr.expandString(context); | |
} | |
public String getSrc(Map<String, Object> context) { | |
return this.srcExdr.expandString(context); | |
} | |
public String getStyle(Map<String, Object> context) { | |
return this.styleExdr.expandString(context); | |
} | |
public String getUrlMode() { | |
return this.urlMode; | |
} | |
public String getWidth(Map<String, Object> context) { | |
return this.widthExdr.expandString(context); | |
} | |
public void renderImageString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) { | |
try { | |
treeStringRenderer.renderImage(writer, context, this); | |
} catch (IOException e) { | |
String errMsg = "Error rendering image with id [" + getId(context) + "]: " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} | |
} | |
} | |
/** | |
* Models the <label> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
public static final class Label { | |
private final FlexibleStringExpander idExdr; | |
private final FlexibleStringExpander styleExdr; | |
private final FlexibleStringExpander textExdr; | |
public Label(Element labelElement) { | |
String textAttr = labelElement.getAttribute("text"); | |
String pcdata = UtilXml.checkEmpty(UtilXml.elementValue(labelElement), ""); | |
this.textExdr = FlexibleStringExpander.getInstance(textAttr + pcdata); | |
this.idExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("id")); | |
this.styleExdr = FlexibleStringExpander.getInstance(labelElement.getAttribute("style")); | |
} | |
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 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 void renderLabelString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) { | |
try { | |
treeStringRenderer.renderLabel(writer, context, this); | |
} catch (IOException e) { | |
String errMsg = "Error rendering label with id [" + getId(context) + "]: " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} | |
} | |
public FlexibleStringExpander getIdExdr() { | |
return idExdr; | |
} | |
public FlexibleStringExpander getStyleExdr() { | |
return styleExdr; | |
} | |
public FlexibleStringExpander getTextExdr() { | |
return textExdr; | |
} | |
} | |
/** | |
* Models the <link> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
public static class Link { | |
private final boolean encode; | |
private final boolean fullPath; | |
private final FlexibleStringExpander idExdr; | |
private final Image image; | |
private final String linkType; | |
private final FlexibleStringExpander nameExdr; | |
private final List<Parameter> parameterList; | |
private final FlexibleStringExpander prefixExdr; | |
private final boolean secure; | |
private final FlexibleStringExpander styleExdr; | |
private final FlexibleStringExpander targetExdr; | |
private final FlexibleStringExpander targetWindowExdr; | |
private final FlexibleStringExpander textExdr; | |
private final FlexibleStringExpander titleExdr; | |
private final String urlMode; | |
public Link(Element linkElement) { | |
this.encode = "true".equals(linkElement.getAttribute("encode")); | |
this.fullPath = "true".equals(linkElement.getAttribute("full-path")); | |
this.idExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("id")); | |
Element imageElement = UtilXml.firstChildElement(linkElement, "image"); | |
if (imageElement != null) { | |
this.image = new Image(imageElement); | |
} else { | |
this.image = null; | |
} | |
this.linkType = linkElement.getAttribute("link-type"); | |
this.nameExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("name")); | |
List<? extends Element> parameterElementList = UtilXml.childElementList(linkElement, "parameter"); | |
if (!parameterElementList.isEmpty()) { | |
List<Parameter> parameterList = new ArrayList<Parameter>(parameterElementList.size()); | |
for (Element parameterElement : parameterElementList) { | |
parameterList.add(new Parameter(parameterElement)); | |
} | |
this.parameterList = Collections.unmodifiableList(parameterList); | |
} else { | |
this.parameterList = Collections.emptyList(); | |
} | |
this.prefixExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("prefix")); | |
this.secure = "true".equals(linkElement.getAttribute("secure")); | |
this.styleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("style")); | |
this.targetExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target")); | |
this.targetWindowExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("target-window")); | |
this.textExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("text")); | |
this.titleExdr = FlexibleStringExpander.getInstance(linkElement.getAttribute("title")); | |
this.urlMode = UtilXml.checkEmpty(linkElement.getAttribute("link-type"), "intra-app"); | |
} | |
// FIXME: Using a widget model in this way is an ugly hack. | |
public Link(String style, String target, String text) { | |
this.encode = false; | |
this.fullPath = false; | |
this.idExdr = FlexibleStringExpander.getInstance(""); | |
this.image = null; | |
this.linkType = ""; | |
this.nameExdr = FlexibleStringExpander.getInstance(""); | |
this.parameterList = Collections.emptyList(); | |
this.prefixExdr = FlexibleStringExpander.getInstance(""); | |
this.secure = false; | |
this.styleExdr = FlexibleStringExpander.getInstance(style); | |
this.targetExdr = FlexibleStringExpander.getInstance(target); | |
this.targetWindowExdr = FlexibleStringExpander.getInstance(""); | |
this.textExdr = FlexibleStringExpander.getInstance(text); | |
this.titleExdr = FlexibleStringExpander.getInstance(""); | |
this.urlMode = "intra-app"; | |
} | |
public boolean getEncode() { | |
return this.encode; | |
} | |
public boolean getFullPath() { | |
return this.fullPath; | |
} | |
public String getId(Map<String, Object> context) { | |
return this.idExdr.expandString(context); | |
} | |
public Image getImage() { | |
return this.image; | |
} | |
public String getLinkType() { | |
return this.linkType; | |
} | |
public String getName(Map<String, Object> context) { | |
return this.nameExdr.expandString(context); | |
} | |
public Map<String, String> getParameterMap(Map<String, Object> context) { | |
Map<String, String> fullParameterMap = new HashMap<String, String>(); | |
/* leaving this here... may want to add it at some point like the hyperlink element: | |
Map<String, String> addlParamMap = this.parametersMapAcsr.get(context); | |
if (addlParamMap != null) { | |
fullParameterMap.putAll(addlParamMap); | |
} | |
*/ | |
for (CommonWidgetModels.Parameter parameter : this.parameterList) { | |
fullParameterMap.put(parameter.getName(), parameter.getValue(context)); | |
} | |
return fullParameterMap; | |
} | |
public String getPrefix(Map<String, Object> context) { | |
return this.prefixExdr.expandString(context); | |
} | |
public boolean getSecure() { | |
return this.secure; | |
} | |
public String getStyle(Map<String, Object> context) { | |
return this.styleExdr.expandString(context); | |
} | |
public String getTarget(Map<String, Object> context) { | |
UtilCodec.SimpleEncoder simpleEncoder = (UtilCodec.SimpleEncoder) context.get("simpleEncoder"); | |
if (simpleEncoder != null) { | |
return this.targetExdr.expandString(UtilCodec.HtmlEncodingMapWrapper.getHtmlEncodingMapWrapper(context, | |
simpleEncoder)); | |
} else { | |
return this.targetExdr.expandString(context); | |
} | |
} | |
public String getTargetWindow(Map<String, Object> context) { | |
return this.targetWindowExdr.expandString(context); | |
} | |
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 getTitle(Map<String, Object> context) { | |
String title = this.titleExdr.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) { | |
title = simpleEncoder.encode(title); | |
} | |
return title; | |
} | |
public String getUrlMode() { | |
return this.urlMode; | |
} | |
public void renderLinkString(Appendable writer, Map<String, Object> context, TreeStringRenderer treeStringRenderer) { | |
try { | |
treeStringRenderer.renderLink(writer, context, this); | |
} catch (IOException e) { | |
String errMsg = "Error rendering link with id [" + getId(context) + "]: " + e.toString(); | |
Debug.logError(e, errMsg, module); | |
throw new RuntimeException(errMsg); | |
} | |
} | |
public FlexibleStringExpander getIdExdr() { | |
return idExdr; | |
} | |
public FlexibleStringExpander getNameExdr() { | |
return nameExdr; | |
} | |
public List<Parameter> getParameterList() { | |
return parameterList; | |
} | |
public FlexibleStringExpander getPrefixExdr() { | |
return prefixExdr; | |
} | |
public FlexibleStringExpander getStyleExdr() { | |
return styleExdr; | |
} | |
public FlexibleStringExpander getTargetExdr() { | |
return targetExdr; | |
} | |
public FlexibleStringExpander getTargetWindowExdr() { | |
return targetWindowExdr; | |
} | |
public FlexibleStringExpander getTextExdr() { | |
return textExdr; | |
} | |
public FlexibleStringExpander getTitleExdr() { | |
return titleExdr; | |
} | |
} | |
/** | |
* Models the <sub-node> element. | |
* | |
* @see <code>widget-tree.xsd</code> | |
*/ | |
public static class ModelSubNode extends ModelWidget { | |
private final List<ModelAction> actions; | |
private final FlexibleStringExpander nodeNameExdr; | |
private final ModelNode rootNode; | |
private final String iteratorKey; | |
public ModelSubNode(Element subNodeElement, ModelNode modelNode) { | |
super(subNodeElement); | |
this.rootNode = modelNode; | |
this.nodeNameExdr = FlexibleStringExpander.getInstance(subNodeElement.getAttribute("node-name")); | |
ArrayList<ModelAction> actions = new ArrayList<ModelAction>(); | |
// FIXME: Validate child elements, should be only one of actions, entity-and, entity-condition, service, script. | |
Element actionsElement = UtilXml.firstChildElement(subNodeElement, "actions"); | |
if (actionsElement != null) { | |
actions.addAll(ModelTreeAction.readSubNodeActions(this, actionsElement)); | |
} | |
Element actionElement = UtilXml.firstChildElement(subNodeElement, "entity-and"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.EntityAnd(this, actionElement)); | |
} | |
actionElement = UtilXml.firstChildElement(subNodeElement, "service"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.Service(this, actionElement)); | |
} | |
actionElement = UtilXml.firstChildElement(subNodeElement, "entity-condition"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.EntityCondition(this, actionElement)); | |
} | |
actionElement = UtilXml.firstChildElement(subNodeElement, "script"); | |
if (actionElement != null) { | |
actions.add(new ModelTreeAction.Script(this, actionElement)); | |
} | |
actions.trimToSize(); | |
this.actions = Collections.unmodifiableList(actions); | |
this.iteratorKey = this.rootNode.getName().concat(".").concat(this.nodeNameExdr.getOriginal()) | |
.concat(".ITERATOR"); | |
} | |
@Override | |
public void accept(ModelWidgetVisitor visitor) throws Exception { | |
visitor.visit(this); | |
} | |
public List<ModelAction> getActions() { | |
return actions; | |
} | |
@SuppressWarnings("unchecked") | |
public ListIterator<? extends Map<String, ? extends Object>> getListIterator(Map<String, Object> context) { | |
return (ListIterator<? extends Map<String, ? extends Object>>) context.get(this.iteratorKey); | |
} | |
public ModelTree.ModelNode getNode() { | |
return this.rootNode; | |
} | |
public String getNodeName(Map<String, Object> context) { | |
return this.nodeNameExdr.expandString(context); | |
} | |
public FlexibleStringExpander getNodeNameExdr() { | |
return nodeNameExdr; | |
} | |
public void setListIterator(ListIterator<? extends Map<String, ? extends Object>> iter, Map<String, Object> context) { | |
context.put(this.iteratorKey, iter); | |
} | |
} | |
} | |
} |