/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.ide.api.project.tree;
import org.eclipse.che.ide.api.event.NodeChangedEvent;
import org.eclipse.che.ide.api.event.RefreshProjectTreeEvent;
import org.eclipse.che.ide.api.project.tree.generic.ProjectNode;
import org.eclipse.che.ide.collections.Array;
import org.eclipse.che.ide.collections.Collections;
import org.eclipse.che.ide.ui.tree.TreeNodeElement;
import com.google.web.bindery.event.shared.EventBus;
import org.vectomatic.dom.svg.ui.SVGImage;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Provides a base implementation of the {@link TreeNode} interface
* to minimize the effort required to implement this interface.
*
* @param <T>
* the type of the associated data
* @author Artem Zatsarynnyy
*/
public abstract class AbstractTreeNode<T> implements TreeNode<T> {
private final TreeStructure treeStructure;
protected EventBus eventBus;
private TreeNode<?> parent;
private T data;
private Array<TreeNode<?>> cachedChildren;
private SVGImage icon;
private TreeNodeElement<TreeNode<?>> treeNodeElement;
/**
* Creates new node with the specified parent and associated data.
*
* @param parent
* parent node
* @param data
* an object this node encapsulates
* @param treeStructure
* {@link TreeStructure} which this node belongs
* @param eventBus
* {@link EventBus}
*/
public AbstractTreeNode(TreeNode<?> parent, T data, TreeStructure treeStructure, EventBus eventBus) {
this.parent = parent;
this.data = data;
this.treeStructure = treeStructure;
this.eventBus = eventBus;
cachedChildren = Collections.createArray();
}
/** {@inheritDoc} */
@Override
public TreeNode<?> getParent() {
return parent;
}
/** {@inheritDoc} */
@Override
public void setParent(TreeNode<?> parent) {
this.parent = parent;
}
/** {@inheritDoc} */
@Override
public T getData() {
return data;
}
/** {@inheritDoc} */
@Override
public void setData(T data) {
this.data = data;
}
/** {@inheritDoc} */
@Nonnull
@Override
public TreeStructure getTreeStructure() {
return treeStructure;
}
/** {@inheritDoc} */
@Nonnull
@Override
public ProjectNode getProject() {
TreeNode<?> candidate = getParent();
while (candidate != null) {
if (candidate instanceof ProjectNode) {
return (ProjectNode)candidate;
}
candidate = candidate.getParent();
}
throw new IllegalStateException("Node is not owned by some project node.");
}
/** {@inheritDoc} */
@Nullable
@Override
public SVGImage getDisplayIcon() {
return icon;
}
/** {@inheritDoc} */
@Override
public void setDisplayIcon(SVGImage icon) {
this.icon = icon;
}
/** {@inheritDoc} */
@Nonnull
@Override
public Array<TreeNode<?>> getChildren() {
return cachedChildren;
}
/** {@inheritDoc} */
@Override
public void setChildren(Array<TreeNode<?>> children) {
cachedChildren = children;
}
/** {@inheritDoc} */
@Override
public void processNodeAction() {
}
/** {@inheritDoc} */
@Override
public boolean isRenamable() {
return false;
}
/** {@inheritDoc} */
@Override
public void rename(String newName, RenameCallback callback) {
eventBus.fireEvent(NodeChangedEvent.createNodeRenamedEvent(this));
callback.onRenamed();
}
/** {@inheritDoc} */
@Override
public boolean isDeletable() {
return false;
}
/** {@inheritDoc} */
@Override
public void delete(DeleteCallback callback) {
if (parent != null) {
parent.getChildren().remove(this);
eventBus.fireEvent(new RefreshProjectTreeEvent(parent));
}
// do not reset parent in order to know which parent this node belonged to before deleting
callback.onDeleted();
}
/** {@inheritDoc} */
@Override
public TreeNodeElement<TreeNode<?>> getTreeNodeElement() {
return treeNodeElement;
}
/** {@inheritDoc} */
@Override
public void setTreeNodeElement(TreeNodeElement<TreeNode<?>> treeNodeElement) {
this.treeNodeElement = treeNodeElement;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AbstractTreeNode)) {
return false;
}
AbstractTreeNode other = (AbstractTreeNode)o;
return Objects.equals(parent, other.parent) && Objects.equals(getId(), other.getId());
}
@Override
public int hashCode() {
return Objects.hash(parent, getId());
}
}