/* * $Id: PageTreeNode.java,v 1.40 2008/06/10 12:53:07 valdas Exp $ * * Copyright (C) 2001-2006 Idega hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. * Use is subject to license terms. * */ package com.idega.builder.business; import java.io.Serializable; import java.rmi.RemoteException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.logging.Logger; import com.idega.builder.data.IBPageName; import com.idega.core.builder.business.BuilderService; import com.idega.core.builder.business.BuilderServiceFactory; import com.idega.core.builder.data.ICPage; import com.idega.core.cache.IWCacheManager2; import com.idega.core.data.ICTreeNode; import com.idega.core.localisation.business.ICLocaleBusiness; import com.idega.data.IDOStoreException; import com.idega.idegaweb.IWApplicationContext; import com.idega.idegaweb.IWMainApplication; import com.idega.presentation.IWContext; import com.idega.util.ListUtil; /** * <p> * Data structure that holds an in memory cache of the Builder * Page tree structure. * </p> * @author <a href="mail:palli@idega.is">Pall Helgason</a>, * <a href="mailto:tryggvi@idega.is">Tryggvi Larusson</a>, * * @version 1.0 */ public class PageTreeNode implements ICTreeNode, Serializable { private static final long serialVersionUID = -6879671702204042851L; private static final Logger LOGGER = Logger.getLogger(PageTreeNode.class.getName()); private static final String CACHE_NAME = "BuilderPageTree"; private int _id = -1; private String _name = null; private List<Integer> childPageIds; private int _order = -1; private transient IWApplicationContext applicationContext; private boolean _isCategory = false; private boolean _isHidden = false; private transient Map<String, String> pageNames; private Integer parentId; protected PageTreeNode(int id, String name) { this(id, name, -1, false, false); } protected PageTreeNode(Integer pageId, String name) { this(pageId.intValue(), name, -1, false, false); } protected PageTreeNode(Integer pageId, String name, int order) { this(pageId.intValue(), name, order, false, false); } protected PageTreeNode(int id, String name, int order) { this(id, name, order, false, false); } protected PageTreeNode(Integer id, String name, boolean isCategory, boolean isHidden) { this(id.intValue(), name, -1, isCategory, isHidden); } protected PageTreeNode(int id, String name, boolean isCategory, boolean isHidden) { this(id, name, -1, isCategory, isHidden); } protected PageTreeNode(Integer pageId, String name, int order, boolean isCategory, boolean isHidden) { this(pageId.intValue(),name,order,isCategory, isHidden); } protected PageTreeNode(int id, String name, int order, boolean isCategory, boolean isHidden) { this._id = id; this._name = name; this.childPageIds = new ArrayList<Integer>(); this._order = order; this._isCategory = isCategory; this._isHidden = isHidden; } public PageTreeNode(int id, IWApplicationContext iwac) { setApplicationContext(iwac); Map<Integer, PageTreeNode> tree = PageTreeNode.getTree(iwac.getIWMainApplication()); PageTreeNode node = tree.get(new Integer(id)); if (node != null) { copyNode(node); } else { this._id = id; this.childPageIds = new ArrayList<Integer>(); } } public PageTreeNode(PageTreeNode clonedNode){ copyNode(clonedNode); } /** * <p> * Copies all the properties from node clonedNode to * this node * </p> * @param clonedNode */ public void copyNode(PageTreeNode clonedNode) { this._id = clonedNode._id; this._name = clonedNode._name; this.parentId = clonedNode.parentId; this.childPageIds = clonedNode.childPageIds; this._order = clonedNode._order; this._isCategory = clonedNode._isCategory; this._isHidden = clonedNode._isHidden; //this._extra = node._extra; this.setPageNames(clonedNode.getPageNames()); } /** * */ public void setNodeId(int id) { this._id = id; } /** * */ public void setNodeName(String name) { this._name = name; } protected static Map<Integer, Map<String, String>> preloadAllNamesFromDatabase() { Map<Integer, Map<String, String>> names = new HashMap<Integer, Map<String, String>>(); Collection<IBPageName> col = TreeNodeFinder.getAllPageNames(); if (!ListUtil.isEmpty(col)) { for (IBPageName nameEntry: col) { int pageId = nameEntry.getPageId(); Integer locId = new Integer(pageId); Map<String, String> localizedNames = names.get(locId); if (localizedNames == null) { localizedNames = new HashMap<String, String>(); names.put(locId, localizedNames); } putLocalizeName(nameEntry, localizedNames); } } return names; } protected Map<String, String> loadNamesFromDatabase(int pageId) { Map<String, String> localizedNames = new HashMap<String, String>(); Collection<IBPageName> col = TreeNodeFinder.getAllPageNames(pageId); if (!ListUtil.isEmpty(col)) { for (IBPageName nameEntry: col) { putLocalizeName(nameEntry,localizedNames); } } return localizedNames; } protected static void putLocalizeName(IBPageName nameEntry, Map<String, String> localizedNames){ int localeId = nameEntry.getLocaleId(); Locale loc = ICLocaleBusiness.getLocale(localeId); StringBuffer localizedKey = new StringBuffer(loc.getLanguage()); String country = loc.getCountry(); if (country != null && !country.equals("")) { localizedKey.append("_"); localizedKey.append(country); } localizedNames.put(localizedKey.toString(), nameEntry.getPageName()); } protected static Map<Integer, PageTreeNode> getTreeFromDatabase() { List<ICPage> page = null; List<ICPage> template = null; List<Integer> rel = null; List<Integer> rel2 = null; Map<Integer, Map<String, String>> pageNames=null; try { page = TreeNodeFinder.listOfAllPages(); rel = TreeNodeFinder.listOfAllPageRelationships(); template = TreeNodeFinder.listOfAllTemplates(); rel2 = TreeNodeFinder.listOfAllTemplateRelationships(); pageNames = preloadAllNamesFromDatabase(); } catch (SQLException e) { e.printStackTrace(); } Map<Integer, PageTreeNode> tree = new Hashtable<Integer, PageTreeNode>(); if (page != null) { for (Iterator<ICPage> pagesIter = page.iterator(); pagesIter.hasNext();) { ICPage pages = pagesIter.next(); PageTreeNode node = null; int order = pages.getTreeOrder(); if (order == -1) { node = new PageTreeNode((Integer)pages.getPrimaryKey(), pages.getName(), pages.isCategory(), pages.isHidePageInMenu()); } else { node = new PageTreeNode((Integer)pages.getPrimaryKey(), pages.getName(), order, pages.isCategory(), pages.isHidePageInMenu()); } node.setPageNames(pageNames.get(pages.getPrimaryKey())); tree.put(new Integer(node.getNodeID()), node); } } if (template != null) { for (Iterator<ICPage> templatesIter = template.iterator(); templatesIter.hasNext();) { ICPage pages = templatesIter.next(); PageTreeNode node = null; int order = pages.getTreeOrder(); if (order == -1) { node = new PageTreeNode((Integer)pages.getPrimaryKey(), pages.getName()); } else { node = new PageTreeNode((Integer)pages.getPrimaryKey(), pages.getName(), order); } node.setPageNames(pageNames.get(pages.getPrimaryKey())); tree.put(new Integer(node.getNodeID()), node); } } if (rel != null) { for (Iterator<Integer> relIter = rel.iterator(); relIter.hasNext();) { Integer parentId = relIter.next(); Integer childId = relIter.next(); PageTreeNode parent = tree.get(parentId); PageTreeNode child = tree.get(childId); if (parent != null) { parent.addChild(child,tree); } if (child != null) { child.setParent(parent); } } } if (rel2 != null) { for (Iterator<Integer> rel2Iter = rel2.iterator(); rel2Iter.hasNext();) { Integer parentId = rel2Iter.next(); Integer childId = rel2Iter.next(); PageTreeNode parent = tree.get(parentId); PageTreeNode child = tree.get(childId); if (parent != null) { parent.addChild(child,tree); } if (child != null) { child.setParent(parent); } } } return tree; } @Override public Collection<PageTreeNode> getChildren() { return getChildren(getTree(getApplicationContext() == null ? IWMainApplication.getDefaultIWMainApplication() : getApplicationContext().getIWMainApplication()) ); } protected Collection<PageTreeNode> getChildren(Map<Integer, PageTreeNode> tree){ List<PageTreeNode> pages = new ArrayList<PageTreeNode>(); Collection<Integer> childIds = getChildIds(); for (Iterator<Integer> iter = childIds.iterator(); iter.hasNext();) { Integer childId = iter.next(); PageTreeNode node = tree.get(childId); pages.add(node); } return pages; } /** * <p> * </p> * @return */ protected List<Integer> getChildIds() { if(this.childPageIds==null){ this.childPageIds=new ArrayList<Integer>(); } return this.childPageIds; } /** * */ @Override public Iterator<PageTreeNode> getChildrenIterator() { return getChildren().iterator(); } /** * */ @Override public boolean getAllowsChildren() { return true; } /** * */ @Override public ICTreeNode getChildAtIndex(int childIndex) { Collection<PageTreeNode> children = getChildren(); if (ListUtil.isEmpty(children)) { return null; } List<PageTreeNode> temp = new ArrayList<PageTreeNode>(children); return childIndex < temp.size() ? temp.get(childIndex) : null; } /** * */ @Override public int getChildCount() { return this.childPageIds.size(); } /** * */ @Override public int getIndex(ICTreeNode node) { return 0; } /** * */ @Override public ICTreeNode getParentNode() { PageTreeNode parent = getTree(getApplicationContext() == null ? IWMainApplication.getDefaultIWMainApplication() : getApplicationContext().getIWMainApplication() ).get(getParentId()); return parent; } /** * */ @Override public boolean isLeaf() { int children = getChildCount(); if (children > 0) { return false; } else { return true; } } /** * Returns the node name for this node */ @Override public String getNodeName() { return this._name; } /** * Returns the Localized node name for this node */ @Override public String getNodeName(Locale locale){ return getLocalizedNodeName(locale); } public String getLocalizedNodeName(IWContext iwc) { Locale curr = iwc.getCurrentLocale(); return getLocalizedNodeName(curr); } public String getLocalizedNodeName(Locale locale) { Map<String, String> pageNames = getPageNames(); if (pageNames == null||pageNames.isEmpty()) { return getNodeName(); } StringBuffer localeString = new StringBuffer(locale.getLanguage()); String country = locale.getCountry(); if (country != null && !country.equals("")) { localeString.append("_"); localeString.append(country); } String localizedName = pageNames.get(localeString.toString()); if (localizedName != null && !localizedName.equals("")) { return localizedName; } return getNodeName(); } public void setLocalizedNodeName(String locale, String name, IWContext iwc) { Map<String, String> pageNames = getPageNames(); pageNames.put(locale, name); } public int getPageId(){ return this._id; } /** * */ @Override public int getNodeID() { return getPageId(); } /** * */ @Override public int getSiblingCount() { return (0); } /** * */ public boolean removeChild(PageTreeNode child) { Integer childId = new Integer(child.getId()); if(this.childPageIds.contains(childId)){ this.childPageIds.remove(childId); return true; } return false; } public boolean addChild(PageTreeNode child) { return addChild(child,null); } /** * */ public boolean addChild(PageTreeNode child, Map<Integer, PageTreeNode> tree) { if (child == null) { return false; } child.setParent(this); Integer childId = new Integer(child.getId()); List<Integer> childPageIds = getChildIds(); if (childPageIds.contains(childId)) { int index = childPageIds.indexOf(childId); childPageIds.add(index, childId); } else { if (childPageIds.isEmpty()) { childPageIds.add(childId); } else { //Check where in the tree this node should be (from the tree_order field) if (child._order < 0) { childPageIds.add(childId); } else { Collection<PageTreeNode> childNodeList; if (tree == null) { childNodeList = getChildren(); } else { childNodeList = getChildren(tree); } if (!ListUtil.isEmpty(childNodeList)) { List<PageTreeNode> temp = new ArrayList<PageTreeNode>(childNodeList); for (ListIterator<PageTreeNode> it = temp.listIterator(); it.hasNext();) { PageTreeNode node = it.next(); if (node._order == -1 || node._order > child._order) { int i = it.previousIndex(); childPageIds.add(i, childId); return true; } } } childPageIds.add(childId); } } } return true; } /** * <p> * </p> * @param node */ private void setParent(PageTreeNode node) { if(node!=null){ this.parentId=new Integer(node.getId()); } } /** * Gets the tree and preloads it and stores in cache */ public static Map<Integer, PageTreeNode> getTree(IWApplicationContext iwac) { return getTree(iwac.getIWMainApplication()); } public static Map<Integer, PageTreeNode> getTree(IWMainApplication iwma) { return getTree(iwma, true); } /** * Gets the tree and preloads it if you set the boolean loadIfEmpty to true */ public static Map<Integer, PageTreeNode> getTree(IWMainApplication iwma, boolean loadIfEmpty) { Map<Integer, PageTreeNode> tree = null; try { tree = IWCacheManager2.getInstance(iwma).getCache(getCacheName(), 10000, true, true); } catch(Exception e) { e.printStackTrace(); } if (tree == null) { getTreeFromDatabase(tree, iwma); } else if (tree.isEmpty() && loadIfEmpty) { getTreeFromDatabase(tree, iwma); } return tree; } private static Map<Integer, PageTreeNode> getTreeFromDatabase(Map<Integer, PageTreeNode> tree, IWMainApplication iwma) { synchronized (iwma) { Map<Integer, PageTreeNode> dbTree = getTreeFromDatabase(); if (dbTree == null) { return tree; } if (tree == null) { tree = new Hashtable<Integer, PageTreeNode>(); } Map.Entry<Integer, PageTreeNode> entry = null; for (Iterator<Map.Entry<Integer, PageTreeNode>> it = dbTree.entrySet().iterator(); it.hasNext();) { entry = it.next(); tree.put(entry.getKey(), entry.getValue()); } } return tree; } /** * <p> * </p> * @return */ private static String getCacheName() { return CACHE_NAME; } /** * Clears the tree from cache * @param iwc */ public static void clearTree(IWApplicationContext iwac) { clearTree(iwac.getIWMainApplication()); } public static void clearTree(IWMainApplication iwma) { getTree(iwma, false).clear(); } /** * */ @Override public boolean equals(Object obj) { if (obj instanceof PageTreeNode) { PageTreeNode node = (PageTreeNode) obj; if (node._id == this._id) { return true; } else { return false; } } else { return false; } } protected IWApplicationContext getApplicationContext(){ if(this.applicationContext==null){ try{ //Workaround solution if iwac is not set normally this.applicationContext = IWContext.getInstance().getApplicationContext(); } catch(Exception e){ System.err.println("PageTreeNode.getIWApplicationContext() : Tried to get IWApplicationContext from runtime but failed : "+e.getMessage()); this.applicationContext=IWMainApplication.getDefaultIWApplicationContext(); } } return this.applicationContext; } /** * @return */ public boolean isCategory() { return this._isCategory; } public boolean isHiddenInMenu() { return this._isHidden; } @Override public String getId(){ return Integer.toString(getNodeID()); } /** * @return the pageNames */ public Map<String, String> getPageNames() { if (this.pageNames==null) { this.pageNames=loadNamesFromDatabase(getPageId()); } return this.pageNames; } public void setPageNames(Map<String, String> pageNames){ this.pageNames=pageNames; } /** * @param applicationContext the applicationContext to set */ protected void setApplicationContext(IWApplicationContext applicationContext) { this.applicationContext = applicationContext; } /** * @return the parentId */ public Integer getParentId() { return this.parentId; } /** * @param parentId the parentId to set */ public void setParentId(Integer parentId) { this.parentId = parentId; } public void setOrder(int order){ this._order = order; } public int getOrder (){ return this._order; } public PageTreeNode fixTreeOrder(PageTreeNode node){ if (node == null) return null; if (node.getChildCount() == 0) return node; List<PageTreeNode> unsortedNodes = new ArrayList<PageTreeNode>(); for (Object o: node.getChildren()) { if (o instanceof PageTreeNode) { unsortedNodes.add((PageTreeNode) o); } else { LOGGER.warning("Object " + o + " is not instance of " + PageTreeNode.class); } } List<PageTreeNode> sortedNodes = new ArrayList<PageTreeNode>(); List<PageTreeNode> nodesLeft = new ArrayList<PageTreeNode>(); List<Integer> sortedNodesIds = new ArrayList<Integer>(); try { for(int i = 0; i < unsortedNodes.size(); i++){ sortedNodes.add(null); } for (int i = 0; i < unsortedNodes.size(); i++) { PageTreeNode childNode = unsortedNodes.get(i); if (childNode == null) { LOGGER.warning("There is null in unsorted pages collection: " + unsortedNodes); continue; } if ((childNode.getOrder() > 0) && (childNode.getOrder() <= sortedNodes.size())){ if (sortedNodes.get(childNode.getOrder() - 1) == null){ sortedNodes.set(childNode.getOrder() - 1, childNode); } else { nodesLeft.add(childNode); unsortedNodes.set(i, null); } } else { nodesLeft.add(childNode); unsortedNodes.set(i, null); } } int nodesLeftIndex = 0; for (int i = 0; i < sortedNodes.size(); i++) { PageTreeNode childNode = null; if (sortedNodes.get(i) == null) { childNode = null; if (nodesLeft.size() > 0 && nodesLeftIndex < nodesLeft.size()) { childNode = nodesLeft.get(nodesLeftIndex); } if (childNode == null) { continue; } childNode.setOrder(i+1); sortedNodes.set(i, childNode); nodesLeftIndex++; BuilderService bservice = null; try { bservice = BuilderServiceFactory.getBuilderService(this.applicationContext); } catch (RemoteException e) { e.printStackTrace(); } ICPage page = bservice.getICPage(childNode.getId()); if (page != null) { page.setTreeOrder(i+1); page.store(); } } try { childNode = sortedNodes.get(i); sortedNodesIds.add(Integer.valueOf(childNode.getId())); } catch (NumberFormatException e) { e.printStackTrace(); } if (sortedNodes.get(i).getChildCount() != 0) sortedNodes.set(i, fixTreeOrder(sortedNodes.get(i))); //fix children } } catch (IDOStoreException e) { e.printStackTrace(); return node; } node.setChildPageIds(sortedNodesIds); return node; } public void setChildPageIds(List<Integer> childPageIds){ this.childPageIds = childPageIds; } @Override public String getNodeName(Locale locale, IWApplicationContext iwac) { return getLocalizedNodeName(locale); } @Override public String toString() { return getId(); } }