in trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuContentHandlerUsingApiImpl.java [149:363]
public void startElement(String nameSpaceUri, String localElemName,
String qualifiedElemName, Attributes attrList)
throws SAXException
{
super.startElement(nameSpaceUri, localElemName, qualifiedElemName,
attrList);
if (_ROOT_NODE.equals(qualifiedElemName))
{
// Unless both of these are specified, don't attempt to load
// the resource bundle.
String resBundle = attrList.getValue(_RES_BUNDLE_ATTR);
String resBundleKey = attrList.getValue(_VAR_ATTR);
if ( (resBundle != null && !"".equals(resBundle))
&& (resBundleKey != null && !"".equals(resBundleKey))
)
{
// Load the resource Bundle.
// Ensure the bundle key is unique by appending the
// handler Id.
MenuUtils.loadBundle(resBundle, resBundleKey + getHandlerId());
_resBundleKey = resBundleKey;
_resBundleName = resBundle;
}
}
else
{
// Either itemNode, destinationNode, or groupNode
boolean isNonSharedNode = ( _ITEM_NODE.equals(qualifiedElemName)
|| _GROUP_NODE.equals(qualifiedElemName)
);
if (isNonSharedNode)
{
_currentNodeStyle = ( _ITEM_NODE.equals(qualifiedElemName)
? MenuConstants.NODE_STYLE_ITEM
: MenuConstants.NODE_STYLE_GROUP
);
_nodeDepth++;
if ((_skipDepth >= 0) && (_nodeDepth > _skipDepth))
{
// This sub-tree is being skipped, so just return
return;
}
if (_menuNodes.size() < _nodeDepth)
{
_menuNodes.add(new ArrayList<MenuNode>());
}
_attrMap = _getMapFromList(attrList);
// Create either an itemNode or groupNode.
MenuNode menuNode = _createMenuNode();
if (menuNode == null)
{
// No menu item is created, so note that we are
// now skipping the subtree
_skipDepth = _nodeDepth;
}
else
{
if ( (_resBundleName != null && !"".equals(_resBundleName))
&& (_resBundleKey != null && !"".equals(_resBundleKey))
)
{
menuNode.setResBundleKey(_resBundleKey);
menuNode.setResBundleName(_resBundleName);
}
// Set the node's MenuContentHandlerUsingApiImpl id so that when
// the node's getLabel() method is called, we can
// use the handlerId to insert into the label
// if it is an EL expression.
menuNode.setHandlerId(getHandlerId());
// Set the root model on the node so we can call into
// the root model from the node to populate its
// idNodeMap (See XMLMenuModel.java)
menuNode.setRootModelKey(getRootModelKey());
// Set the local model (created when parsing a sharedNode)
// on the node in case the node needs to get back to its
// local model.
menuNode.setModelId(getModelId());
// menu nodes need to know how to refer
// back to the specific xml menu model
// so that they can mutate them.
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap =
facesContext.getExternalContext().getRequestMap();
if(!requestMap.containsKey(XMLMenuModel.SHARED_MODEL_INDICATOR_KEY))
menuNode.setRootId( (getId() ) );
else
menuNode.setRootId((Integer) requestMap.get(XMLMenuModel.SHARED_MODEL_INDICATOR_KEY));
List<MenuNode> list = _menuNodes.get(_nodeDepth-1);
list.add(menuNode.getThreadSafeCopy());
}
}
else if (_SHARED_NODE.equals(qualifiedElemName))
{
_nodeDepth++;
// SharedNode's "ref" property points to another submenu's metadata,
// and thus a new model, which we build here. Note: this will
// recursively call into this MenuContentHandlerUsingApiImpl when parsing the
// submenu's metadata.
String expr = attrList.getValue(_REF_ATTR);
// push this only when we are root model
FacesContext facesContext = FacesContext.getCurrentInstance();
Map<String, Object> requestMap =
facesContext.getExternalContext().getRequestMap();
Integer recurseLevel = (Integer) requestMap.get(_RECURSE_COUNTER);
if(recurseLevel == null)
recurseLevel = 0;
if(recurseLevel == 0)
requestMap.put(XMLMenuModel.SHARED_MODEL_INDICATOR_KEY, this.getId());
recurseLevel++;
requestMap.put(_RECURSE_COUNTER, recurseLevel);
// Need to push several items onto the stack now as we recurse
// into another menu model.
_saveModelData();
// Create the sub menu model specified in the sharedNode
XMLMenuModel menuModel = (XMLMenuModel)MenuUtils.getBoundValue(expr,
Object.class);
// Now must pop the values cause we are back to the parent
// model.
_restoreModelData();
recurseLevel = (Integer) requestMap.get(_RECURSE_COUNTER);
recurseLevel --;
requestMap.put(_RECURSE_COUNTER, recurseLevel);
if(recurseLevel == 0)
requestMap.remove(XMLMenuModel.SHARED_MODEL_INDICATOR_KEY);
// Name of the managed bean that is the sub menu XMLMenuModel.
String modelStr = expr.substring(expr.indexOf('{')+1,
expr.indexOf('}'));
// There are 2 ways that a Model can be invalid:
// 1) Something such as a missing managed bean definition
// for the submenu model causes the creation of the
// XMLMenuModel for the submenu to fail. This will result
// in menuModel being NULL.
// 2) Some kind of parsing error in its metadata. If a node
// type is invalid, an exception will be thrown (see below)
// and caught in getTreeModel(). This will result in a
// null submenu list the following SAXException will also
// be logged.
if (menuModel != null)
{
Object subMenuObj = menuModel.getWrappedData();
List<MenuNode> subMenuList = null;
if (subMenuObj instanceof ChildPropertyTreeModel)
{
subMenuList =
(List<MenuNode>)((ChildPropertyTreeModel)subMenuObj).getWrappedData();
}
if (subMenuList != null)
{
// SharedNode could be the first child
// So we need a new list for the children
if (_menuNodes.size() < _nodeDepth)
{
_menuNodes.add(new ArrayList<MenuNode>());
}
List<MenuNode> list = _menuNodes.get(_nodeDepth-1);
list.addAll(subMenuList);
}
else
{
// Let it go through but log it. This way the rest of
// the Tree gets built and this submenu is skipped.
SAXException npe =
new SAXException("Shared Node Model not created for " + modelStr);
}
}
else
{
// Let it go through but log it. This way the rest of
// the Tree gets built and this submenu is skipped.
NullPointerException npe =
new NullPointerException("Shared Node Model not created for "
+ modelStr + ". Check for the existence of the corresponding "
+ "managed bean in your config files.");
_LOG.severe (npe.getMessage(), npe);
}
}
else
{
// Throw an Exception for any node that is not of type
// menu, itemNode, groupNode, or sharedNode. This will get
// caught in getTreeModel()
throw new SAXException("Invalid Node type: " + localElemName);
}
}
}