/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.pms.ui.tree; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.TreeMap; import org.eclipse.swt.graphics.Image; import org.pentaho.pms.schema.concept.ConceptUtilityBase; import org.pentaho.pms.ui.jface.tree.ITreeNode; import org.pentaho.pms.ui.jface.tree.TreeNode; import org.pentaho.pms.util.ObjectAlreadyExistsException; import org.pentaho.pms.util.UniqueList; public abstract class ConceptTreeNode extends TreeNode { public ConceptTreeNode(ITreeNode parent) { super(parent); } /** * */ protected abstract void createChildren(List children); /** * * */ public abstract void sync(); public String getName() { return null; } public String getId() { if (getDomainObject() instanceof ConceptUtilityBase) { return ((ConceptUtilityBase) getDomainObject()).getId(); } return null; } public int getDragAndDropType() { return 0; } /** * * @return */ public String getConceptName() { return null; } /** * * @return */ public Image getConceptImage() { return null; } /** * * @return the business object that this Concept TreeNode is holdinng */ public abstract Object getDomainObject(); public abstract void addDomainChild(Object obj); /** * * @param businessObject * an object from the meta-model - ie., BusinessTable, * BusinessColumn, etc. * @return the node that this business object lives in */ public ConceptTreeNode findNode(Object businessObject) { ConceptTreeNode node = null; // GEM - this if statement gets us around a bug where // some Kettle objects equals() methods are overridden, // and they are not able to compare two different classes if (getDomainObject().getClass().equals(businessObject.getClass())) { if (getDomainObject().equals(businessObject)) node = this; } Iterator iter = getChildren().iterator(); while ((iter.hasNext()) && (node == null)) { ConceptTreeNode childNode = (ConceptTreeNode) iter.next(); node = childNode.findNode(businessObject); } return node; } /** * moves a specific child up one. Call * to sync() forces the model to reflect the view. * * @param child child to move */ public void moveChildUp(ITreeNode child) { int index = fChildren.indexOf(child); if (index != 0) { fChildren.remove(index); fChildren.add(index - 1, child); sync(); } } /** * moves a specific child down one. Call * to sync() forces the model to reflect the view. * * @param child child to move */ public void moveChildDown(ITreeNode child) { int index = fChildren.indexOf(child); if (index != fChildren.size() - 1) { fChildren.remove(index); if (index != fChildren.size() - 1) { fChildren.add(index + 1, child); } else { fChildren.add(child); } sync(); } } /** * recursively sort the child nodes in ascending order, then synchronize the * changes * */ public void sortChildrenAscending() { if (!hasChildren()) return; TreeMap<String, ConceptTreeNode> map = new TreeMap<String, ConceptTreeNode>(); Collection children = getChildren(); for (Iterator iter = children.iterator(); iter.hasNext();) { ConceptTreeNode element = (ConceptTreeNode) iter.next(); map.put(element.getName(), element); element.sortChildrenAscending(); } fChildren.clear(); Iterator keyIter = map.keySet().iterator(); while (keyIter.hasNext()) { String key = (String) keyIter.next(); fChildren.add(map.get(key)); } sync(); } /** * Synchronize the node hierarchy with it's business model * * @param modelList * the list of business objects from the business model that we * will sync with */ @SuppressWarnings("unchecked") public void sync(UniqueList modelList) { if (fChildren == null) { getChildren(); } // make copy of list so removals doesn't cause a problem Iterator childIter = fChildren.iterator(); List children = new ArrayList(); while (childIter.hasNext()) children.add(childIter.next()); ConceptTreeNode element = null; // Check the business model for additions, add children if they exist for (int c = 0; c < modelList.size(); c++) { boolean found = false; for (Iterator iter = children.iterator(); iter.hasNext();) { element = (ConceptTreeNode) iter.next(); if (element.getDomainObject().equals(modelList.get(c))) { found = true; break; } } // if not found, then add it to the node... if (!found) { addDomainChild(modelList.get(c)); } } // Check the children against the business model to see if any should be // removed... // Recursively sync the children that remain for (int c = 0; c < children.size(); c++) { ConceptTreeNode node = (ConceptTreeNode) children.get(c); if (!modelList.contains(node.getDomainObject())) { removeChild(node); } else { node.sync(); } } syncIndexing(modelList); // update this node fireTreeNodeUpdated(); } @SuppressWarnings("unchecked") protected void syncIndexing(UniqueList modelList) { // make copy of list so removals doesn't cause a problem Iterator modelIter = modelList.iterator(); List modelChildren = new ArrayList(); while (modelIter.hasNext()) modelChildren.add(modelIter.next()); int childIndex = -1, modelIndex = -1; for (int i = 0; i < fChildren.size(); i++) { ConceptTreeNode element = (ConceptTreeNode) fChildren.get(i); modelIndex = modelList.indexOf(element.getDomainObject()); // We want to make sure the index is right.... // We may have sorted the nodes which would put the tree and the // model indexes out of sync if (i != modelIndex) { childIndex = i; modelList.remove(modelIndex); try { if (childIndex < modelList.size()) modelList.add(childIndex, element.getDomainObject()); else modelList.add(element.getDomainObject()); } catch (ObjectAlreadyExistsException e) { //should not happen! } } } } }