/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.ui.rcp.provider.contentprovider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jubula.client.core.businessprocess.CompNameManager; import org.eclipse.jubula.client.core.events.DataChangedEvent; import org.eclipse.jubula.client.core.events.DataEventDispatcher; import org.eclipse.jubula.client.core.events.DataEventDispatcher.DataState; import org.eclipse.jubula.client.core.events.DataEventDispatcher.IDataChangedListener; import org.eclipse.jubula.client.core.events.DataEventDispatcher.IProjectLoadedListener; import org.eclipse.jubula.client.core.events.DataEventDispatcher.UpdateState; import org.eclipse.jubula.client.core.model.IComponentNamePO; import org.eclipse.jubula.client.core.model.IObjectMappingPO; import org.eclipse.jubula.client.core.model.IPersistentObject; import org.eclipse.jubula.client.core.model.IProjectPO; import org.eclipse.jubula.client.core.model.IReusedProjectPO; import org.eclipse.jubula.client.core.model.ITestCasePO; import org.eclipse.jubula.client.core.model.ITestSuitePO; import org.eclipse.jubula.client.core.persistence.GeneralStorage; import org.eclipse.jubula.client.core.persistence.ProjectPM; import org.eclipse.jubula.client.ui.constants.Constants; import org.eclipse.jubula.client.ui.constants.IconConstants; import org.eclipse.jubula.client.ui.rcp.Plugin; import org.eclipse.jubula.client.ui.rcp.i18n.Messages; import org.eclipse.jubula.client.ui.rcp.provider.labelprovider.TooltipLabelProvider; import org.eclipse.jubula.client.ui.utils.LayoutUtil; import org.eclipse.jubula.tools.internal.constants.StringConstants; import org.eclipse.jubula.tools.internal.exception.Assert; import org.eclipse.jubula.tools.internal.exception.JBException; import org.eclipse.jubula.tools.internal.i18n.CompSystemI18n; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; /** * The ContentProvider for the Component Names Browser including the Label * and Color Provider * * @author BREDEX GmbH * @created 06.02.2009 */ public class ComponentNameBrowserContentProvider extends TooltipLabelProvider implements ITreeContentProvider, IColorProvider, IProjectLoadedListener, IDataChangedListener { /** The color for disabled elements */ private static final Color DISABLED_COLOR = LayoutUtil.GRAY_COLOR; /** dummy object to return */ private static final Object[] DUMMY = new Object[0]; /** the tree viewer */ private TreeViewer m_viewer; /** the child <-> parent relationship map */ private Map<Object, Object> m_relationShip = new HashMap<Object, Object>(117); /** the parent->children cache */ private Map<Object, List<Object>> m_children = new HashMap<Object, List<Object>>(79); /** * register handler for project load and data change to clear caches */ public ComponentNameBrowserContentProvider() { DataEventDispatcher ded = DataEventDispatcher.getInstance(); ded.addProjectLoadedListener(this, true); ded.addDataChangedListener(this, false); } /** * Drops all cached data. */ private void clearCaches() { m_relationShip.clear(); m_children.clear(); } /** * {@inheritDoc} */ public void handleProjectLoaded() { clearCaches(); } /** {@inheritDoc} */ public void handleDataChanged(DataChangedEvent... events) { boolean refreshView = false; for (DataChangedEvent e : events) { if (e.getUpdateState() != UpdateState.onlyInEditor && (e.getPo() instanceof IComponentNamePO || ((e.getDataState() == DataState.Saved) && (e.getPo() instanceof IObjectMappingPO) || (e.getPo() instanceof ITestCasePO) || (e.getPo() instanceof ITestSuitePO)))) { refreshView = true; break; } } if (refreshView) { clearCaches(); } } /** * {@inheritDoc} */ public Object[] getChildren(Object parentO) { List<Object> cachedChildren = m_children.get(parentO); if (cachedChildren != null) { return cachedChildren.toArray(); } Object[] children = DUMMY; if (parentO instanceof IProjectPO || parentO instanceof IReusedProjectPO) { children = handleProjectTree(parentO); } if (parentO instanceof AbstractCompNamesCategory) { AbstractCompNamesCategory pe = (AbstractCompNamesCategory)parentO; if (pe instanceof UsedCompnamesCategory) { children = CompNameManager.getInstance(). getUsedCompNames(pe.m_parentProjectID); } if (pe instanceof UnusedCompnamesCategory) { children = CompNameManager.getInstance(). getUnusedCompNames(pe.m_parentProjectID); } if (pe instanceof ReusedCompnamesCategory) { children = findAllReusedProjects(pe); } } if (children != DUMMY) { List <Object>childrenList = new ArrayList<Object>(children.length); for (Object o : children) { m_relationShip.put(o, parentO); childrenList.add(o); } m_children.put(parentO, childrenList); } return children; } /** * @param parentO a Project or ReusedProject as root * @return an array of the parent children */ private Object[] handleProjectTree(Object parentO) { Long parentProjectID = null; Object[] children = DUMMY; if (parentO instanceof IProjectPO) { parentProjectID = ((IProjectPO)parentO).getId(); } else { IReusedProjectPO rp = ((IReusedProjectPO)parentO); try { parentProjectID = ProjectPM.findProjectId(rp .getProjectGuid(), rp.getMajorNumber(), rp .getMinorNumber(), rp.getMicroNumber(), rp .getVersionQualifier()); } catch (JBException e) { // do nothing } } if (parentProjectID != null) { UsedCompnamesCategory usedCat = new UsedCompnamesCategory( parentProjectID, parentO); UnusedCompnamesCategory unCat = new UnusedCompnamesCategory( parentProjectID, parentO); try { boolean areThereReusedProjects; if (parentO instanceof IProjectPO) { IProjectPO project = (IProjectPO) parentO; areThereReusedProjects = project.getUsedProjects() .size() > 0; } else { areThereReusedProjects = ProjectPM.getReusedProjectsForProjectRO( parentProjectID).size() > 0; } if (areThereReusedProjects) { ReusedCompnamesCategory reusedCat = new ReusedCompnamesCategory( parentProjectID, parentO); children = new AbstractCompNamesCategory[] { usedCat, unCat, reusedCat }; } else { children = new AbstractCompNamesCategory[] { usedCat, unCat }; } } catch (JBException e) { // nothing to catch here } } return children; } /** * @param pe * the parent element * @return a list of all reused project pos */ private Object[] findAllReusedProjects(AbstractCompNamesCategory pe) { try { List<IReusedProjectPO> usedProjects = ProjectPM .getReusedProjectsForProjectRO(pe.getParentProjectID()); return usedProjects.toArray(); } catch (JBException e) { // nothing to catch here } return DUMMY; } /** {@inheritDoc} */ public Object getParent(Object element) { return m_relationShip.get(element); } /** * {@inheritDoc} */ public boolean hasChildren(Object element) { List<Object> children = m_children.get(element); if (children != null) { return !children.isEmpty(); } return getChildren(element).length != 0; } /** * {@inheritDoc} */ public Object[] getElements(Object inputElement) { List<Object> children = m_children.get(inputElement); if (children != null) { return children.toArray(); } return getChildren(inputElement); } /** * {@inheritDoc} */ public void dispose() { clearCaches(); DataEventDispatcher ded = DataEventDispatcher.getInstance(); ded.removeProjectLoadedListener(this); ded.removeDataChangedListener(this); } /** * {@inheritDoc} */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (viewer instanceof TreeViewer) { setViewer((TreeViewer)viewer); } if (oldInput != newInput) { clearCaches(); } } /** * {@inheritDoc} */ public String getText(Object element) { if (element instanceof AbstractCompNamesCategory) { return ((AbstractCompNamesCategory)element).getName(); } if (element instanceof IComponentNamePO) { IComponentNamePO cName = ((IComponentNamePO)element); cName = CompNameManager.getInstance().getResCompNamePOByGuid( cName.getGuid()); String cType = CompSystemI18n.getString(cName.getComponentType()); String displayName = cName.getName() + StringConstants.SPACE + StringConstants.LEFT_BRACKET + cType + StringConstants.RIGHT_BRACKET; int count = CompNameManager.getInstance(). getUsageByGuid(cName.getGuid()); if (Plugin.getDefault().getPreferenceStore() .getBoolean(Constants.SHOWCOUNTERS_KEY)) { displayName += StringConstants.SPACE + StringConstants.LEFT_PARENTHESIS + CompNameManager.getInstance(). getUsageByGuid(cName.getGuid()) + StringConstants.RIGHT_PARENTHESIS; } return displayName; } if (element instanceof IPersistentObject) { IPersistentObject node = ((IPersistentObject)element); if (node.getName() != null) { return node.getName(); } return node.toString(); } Assert.notReached( org.eclipse.jubula.client.ui.i18n.Messages .UnknownTypeOfElementInTreeOfType + StringConstants.SPACE + element.getClass().getName()); return super.getText(element); } /** * {@inheritDoc} */ public Image getImage(Object element) { if (element instanceof IComponentNamePO) { return IconConstants.LOGICAL_NAME_IMAGE; } if (element instanceof IReusedProjectPO) { return IconConstants.PROJECT_IMAGE; } if (element instanceof AbstractCompNamesCategory) { return IconConstants.CATEGORY_IMAGE; } return super.getImage(element); } /** * @return the viewer */ public TreeViewer getViewer() { return m_viewer; } /** * @param viewer the viewer to set */ private void setViewer(TreeViewer viewer) { m_viewer = viewer; } /** * {@inheritDoc} */ public Color getBackground(Object element) { return null; } /** * {@inheritDoc} */ public Color getForeground(Object element) { IProjectPO cp = GeneralStorage.getInstance().getProject(); if (cp != null) { // only local component names if (element instanceof IComponentNamePO && cp.getId().equals( ((IComponentNamePO)element).getParentProjectId())) { return null; } // and local component name categories should appear editable if (element instanceof UsedCompnamesCategory || element instanceof UnusedCompnamesCategory) { AbstractCompNamesCategory ac = (AbstractCompNamesCategory)element; if (ac.getParentProjectID() == cp.getId()) { return null; } } } return DISABLED_COLOR; } /** * A synthetic GUI class * * @author BREDEX GmbH * @created 10.02.2009 */ public abstract class AbstractCompNamesCategory { /** The name of this node */ private String m_name; /** The parent of this node */ private long m_parentProjectID; /** the parent object of this node */ private Object m_parent; /** * {@inheritDoc} */ public boolean equals(Object obj) { if (obj instanceof AbstractCompNamesCategory) { AbstractCompNamesCategory sg = (AbstractCompNamesCategory)obj; return new EqualsBuilder(). append(m_name, sg.getName()). append(m_parent, sg.getParent()). isEquals(); } return super.equals(obj); } /** * {@inheritDoc} */ public int hashCode() { return new HashCodeBuilder(). append(m_name). append(m_parent). toHashCode(); } /** * @return the parent */ public Object getParent() { return m_parent; } /** * @param parent the parent to set */ public void setParent(Object parent) { m_parent = parent; } /** * @return the parentProjectID */ public long getParentProjectID() { return m_parentProjectID; } /** * @param parentProjectID * the parentProjectID to set */ public void setParentProjectID(long parentProjectID) { m_parentProjectID = parentProjectID; } /** * @return the name */ public String getName() { return m_name; } /** * @param name * the name to set */ public void setName(String name) { m_name = name; } } /** * A synthetic GUI class for used component names * * @author BREDEX GmbH * @created 16.02.2009 */ public class UsedCompnamesCategory extends AbstractCompNamesCategory { /** * @param parentID * the parent project id * @param parent * the parent object */ public UsedCompnamesCategory(long parentID, Object parent) { setName(Messages.CompNameBrowserUsedCat); setParentProjectID(parentID); setParent(parent); } } /** * A synthetic GUI class for unused component names * * @author BREDEX GmbH * @created 16.02.2009 */ public class UnusedCompnamesCategory extends AbstractCompNamesCategory { /** The children component names */ private Set<IComponentNamePO> m_compNames; /** * @param parentID * the parent project id * @param parent * the parent object */ public UnusedCompnamesCategory(long parentID, Object parent) { setName(Messages.CompNameBrowserUnusedCat); setParentProjectID(parentID); setParent(parent); } } /** * A synthetic GUI class for unused component names * * @author BREDEX GmbH * @created 16.02.2009 */ public class ReusedCompnamesCategory extends AbstractCompNamesCategory { /** * @param parentID * the parent project id * @param parent * the parent object */ public ReusedCompnamesCategory(long parentID, Object parent) { setName(Messages.CompNameBrowserReusedCat); setParentProjectID(parentID); setParent(parent); } } }