package com.onaro.sanscreen.client.view.init; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Element; import com.onaro.commons.xml.xpath.XPathUtils; import com.onaro.sanscreen.client.view.ActionFactory; import com.onaro.sanscreen.client.view.ActionFactory.ActionInitInfo; import com.onaro.util.InvalidConfigException; import com.onaro.util.xml.XmlIterator; public class ActionsInitInfo implements Cloneable { /** * Caches pointers into the configuration to allow the configuratoin to refer to previously defined blocks. */ private final static Map cachedInitInfos = new HashMap(); private Map nameToActionInitInfo = new HashMap(); private String targetViewType; public ActionsInitInfo(String targetViewType) { this.targetViewType = targetViewType; } public ActionsInitInfo(XmlIterator xmlIterator2, String targetViewType) throws InvalidConfigException { this(targetViewType); Element xmlIteratorNode = (Element)xmlIterator2.getNode(); List actionElements = getActionElements(xmlIteratorNode); if(actionElements != null) { for (Element actionElement : actionElements) { /** * Create the actionInitInfo and save it. */ String actionType = actionElement.getAttribute("type"); //$NON-NLS-1$ if (StringUtils.isBlank(actionType)) { String actionElementPath = XPathUtils.getPath(actionElement); throw new InvalidConfigException("Mandatory attribute 'type' is missing at '" + actionElementPath + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } String actionName = actionElement.getAttribute("name"); //$NON-NLS-1$ if (StringUtils.isBlank(actionName)) { String actionElementPath = XPathUtils.getPath(actionElement); throw new InvalidConfigException("Mandatory attribute 'name' is missing in '" + actionElementPath + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } boolean clone = Boolean.parseBoolean(actionElement.getAttribute("clone")); //$NON-NLS-1$ XmlIterator actionXmlIterator = new XmlIterator(actionElement); ActionFactory.ActionInitInfo actionInitInfo; if (clone) { // should be used only for the properties configuration actionInitInfo = getCachedActionInfo(actionXmlIterator, actionType, actionName); } else { actionInitInfo = ActionFactory.getActionInitInfo(actionName, actionType, targetViewType, actionXmlIterator); addCacheActionInfo(actionInitInfo); } nameToActionInitInfo.put(actionName, actionInitInfo); } } } /* Returns a list of action element nodes from the given parent of a menuactions element or null if none could * be found. This method assumes that the element only has elements. */ private static List getActionElements(Element menuActionsParent) { // We expect to only find one menuactions child element Element menuActions = XPathUtils.getFirstChildElementByTagName(menuActionsParent, "menuactions"); //$NON-NLS-1$ if(menuActions == null) { return null; } return(XPathUtils.getChildElementsByTagName(menuActions, "action")); //$NON-NLS-1$ } private static String getCacheKey(String type, String name) { return type + "#" + name; //$NON-NLS-1$ } private static void addCacheActionInfo(ActionFactory.ActionInitInfo actionInitInfo) { String cacheKey = getCacheKey(actionInitInfo.getActionType(), actionInitInfo.getActionName()); cachedInitInfos.put(cacheKey, actionInitInfo); } private static ActionFactory.ActionInitInfo getCachedActionInfo(XmlIterator confItr, String type, String name) throws InvalidConfigException { ActionFactory.ActionInitInfo cached = cachedInitInfos.get(getCacheKey(type, name)); if (cached != null) { return cached; } XmlIterator rootItr = new XmlIterator(confItr); while (rootItr.hasUp()) rootItr.up(); /** * Search for the block that defines the requested type and name */ Stack parents = new Stack(); parents.push(rootItr); while (!parents.isEmpty()) { XmlIterator itr = parents.pop(); /** * For each node, test if its of the requested type and nama and isn't a clone. */ if (itr.getName().equals(type)) { String currentName = itr.getAttribute("name"); //$NON-NLS-1$ boolean clone = itr.getBooleanAttribute("clone"); //$NON-NLS-1$ if (!clone && name.equals(currentName)) { ActionFactory.ActionInitInfo actionInitInfo = ActionFactory.getActionInitInfo(name, type, null, confItr); cachedInitInfos.put(getCacheKey(type, name), actionInitInfo); return actionInitInfo; } } /** * Push the childs of this node to the stack. */ for (XmlIterator child = (new XmlIterator(itr)).down(); child.isValid(); child.next()) { parents.push(new XmlIterator(child)); } } throw new InvalidConfigException("Couldn't find the block to clone for type='" + type + "' name='" + name + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public Collection getActionNames() { return nameToActionInitInfo.keySet(); } public ActionFactory.ActionInitInfo getActionInitInfo(String actionName) { return nameToActionInitInfo.get(actionName); } public ActionFactory.ActionInitInfo addAction(String actionName, String actionType) { ActionInitInfo actionInitInfo = ActionFactory.getActionInitInfo(actionName, actionType, targetViewType, null); addCacheActionInfo(actionInitInfo); nameToActionInitInfo.put(actionName, actionInitInfo); return actionInitInfo; } public static ActionFactory.ActionInitInfo getCachedActionInitInfo(String type, String name) { return cachedInitInfos.get(getCacheKey(type, name)); } @Override public ActionsInitInfo clone() throws CloneNotSupportedException { return (ActionsInitInfo) super.clone(); } }