package org.sef4j.core.helpers.proptree.dto; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; /** * DTO for PropTreeNode * * (simpler structure without child->parent relation, and no read-write lock) * <p/> * @see *  org.sef4j.callstack.stattree.CallTreeNode */ public final class PropTreeNodeDTO implements Serializable { /** for java.io.Serializable */ private static final long serialVersionUID = 1L; private final String name; private LinkedHashMap<String,PropTreeNodeDTO> childMap; private Map<String,Object> propsMap; // ------------------------------------------------------------------------ /** * should be called only for ROOT element, or using CallTreeNode.getOrCreateChild(name) */ private PropTreeNodeDTO(String name) { this.name = name; } public static PropTreeNodeDTO newRoot() { return new PropTreeNodeDTO(""); } // ------------------------------------------------------------------------ public String getName() { return name; } @SuppressWarnings("unchecked") public Map<String,PropTreeNodeDTO> getChildMap() { return (childMap != null)? childMap : (Map<String,PropTreeNodeDTO>)Collections.EMPTY_MAP; } /** * @param childName * @return child with name "childName", newly created if did not exist before */ public PropTreeNodeDTO getOrCreateChild(String childName) { PropTreeNodeDTO res = (childMap != null)? childMap.get(childName) : null; if (res == null) { res = new PropTreeNodeDTO(childName); LinkedHashMap<String, PropTreeNodeDTO> newChildMap = new LinkedHashMap<String, PropTreeNodeDTO>(childMap != null? childMap.size() + 1 : 1); if (childMap != null) { newChildMap.putAll(childMap); } newChildMap.put(childName, res); this.childMap = newChildMap; } return res; } /** * helper method for repeating getOrCreateChild() with path elements * @param path * @return sub-sub child for path names */ public PropTreeNodeDTO getOrCreateChildPath(String[] path) { PropTreeNodeDTO res = this; final int len = path.length; for (int i = 0; i < len; i++) { res = res.getOrCreateChild(path[i]); } return res; } /** * @param propName * @return prop with name "propName", newly created if did not exist before */ @SuppressWarnings("unchecked") public <T> T getOrCreateProp(String propName, Callable<T> valueFactory) { T res = (T) propsMap.get(propName); if (res == null) { try { res = valueFactory.call(); } catch (Exception ex) { throw new RuntimeException("Failed to create prop value", ex); } HashMap<String, Object> newPropsMap = new HashMap<String, Object>(propsMap.size() + 1); newPropsMap.putAll(propsMap); newPropsMap.put(propName, res); this.propsMap = newPropsMap; } return res; } @SuppressWarnings("unchecked") public <T> T getProp(String propName) { return (T) propsMap.get(propName); } @SuppressWarnings("unchecked") public <T> T putProp(String propName, T propValue) { if (propsMap == null) { propsMap = new HashMap<String, Object>(); } return (T) propsMap.put(propName, propValue); } public Map<String, Object> getPropsMap() { return propsMap; } public void setPropsMap(Map<String, Object> p) { this.propsMap = p; } // ------------------------------------------------------------------------ @Override public String toString() { return "PropTreeNodeDTO[" + name + "]"; } }