/* Copyright 2011-2016 Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.google.security.zynamics.binnavi.disassembly; import com.google.common.base.Preconditions; import com.google.security.zynamics.binnavi.CUtilityFunctions; import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntDeleteException; import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntLoadDataException; import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntSaveDataException; import com.google.security.zynamics.binnavi.Database.Interfaces.SQLProvider; import com.google.security.zynamics.binnavi.Gui.GraphWindows.CommentDialogs.Interfaces.IComment; import com.google.security.zynamics.binnavi.Gui.Users.CUserManager; import com.google.security.zynamics.binnavi.Tagging.CTag; import com.google.security.zynamics.zylib.disassembly.IAddress; import com.google.security.zynamics.zylib.gui.zygraph.nodes.IViewNodeListener; import java.awt.Color; import java.util.List; import java.util.Set; /** * Represents a function node inside a view. */ public final class CFunctionNode extends CNaviViewNode implements INaviFunctionNode { /** * The function that is represented by the node. */ private final INaviFunction m_function; /** * SQL provider that writes changes of the node to the database. */ private final SQLProvider m_provider; /** * Listener that keeps the code node synchronized with changes in the comment manager. */ private final CommentListener m_internalCommentListener = new InternalCommentListener(); /** * Creates a new function node. * * @param nodeId The ID of the node. * @param function The function that is represented by the node. * @param x The X coordinate of the node in the view. * @param y The Y coordinate of the node in the view. * @param width The width of the node in the graph. * @param height The height of the node in the graph. * @param color The background color of the node. * @param selected Selection state of the node. * @param visible Visibility state of the node. * @param localComments Local comment of the node. * @param tags Tags the node is tagged with. * @param provider SQL provider that writes changes of the node to the database. */ public CFunctionNode(final int nodeId, final INaviFunction function, final double x, final double y, final double width, final double height, final Color color, final boolean selected, final boolean visible, final List<IComment> localComments, final Set<CTag> tags, final SQLProvider provider) { super(nodeId, x, y, width, height, color, Color.BLACK, selected, visible, tags, provider); m_function = Preconditions.checkNotNull(function, "IE00086: Function argument can not be null"); m_provider = Preconditions.checkNotNull(provider, "IE02390: provider argument can not be null"); CommentManager.get(m_provider).addListener(m_internalCommentListener); CommentManager.get(m_provider).initializeFunctionNodeComment(this, localComments); } @Override public List<IComment> appendLocalFunctionComment(final String commentText) throws CouldntSaveDataException, CouldntLoadDataException { return CommentManager.get(m_provider).appendFunctionNodeComment(this, commentText); } @Override public CFunctionNode cloneNode() { return new CFunctionNode(1, getFunction(), getX(), getY(), getWidth(), getHeight(), getColor(), isSelected(), isVisible(), getLocalFunctionComment(), getTags(), m_provider); } @Override public void deleteLocalFunctionComment(final IComment comment) throws CouldntDeleteException { CommentManager.get(m_provider).deleteFunctionNodeComment(this, comment); } @Override public IComment editLocalFunctionComment(final IComment oldComment, final String commentText) throws CouldntSaveDataException { return CommentManager.get(m_provider).editFunctionNodeComment(this, oldComment, commentText); } @Override public IAddress getAddress() { return m_function.getAddress(); } @Override public List<IComment> getLocalFunctionComment() { return CommentManager.get(m_provider).getFunctionNodeComment(this); } @Override public INaviFunction getFunction() { return m_function; } @Override public List<IComment> getLocalComment() { return getLocalFunctionComment(); } @Override public void initializeLocalFunctionComment(final List<IComment> comments) { CommentManager.get(m_provider).initializeFunctionNodeComment(this, comments); } @Override public boolean isOwner(final IComment comment) { Preconditions.checkNotNull(comment, "IE02534: comment argument can not be null"); return CUserManager.get(m_provider).getCurrentActiveUser().equals(comment.getUser()); } @Override public boolean isStored() { return super.isStored(); } @Override public void close() { super.close(); CommentManager.get(m_provider).unloadFunctionNodeComment(this, getLocalFunctionComment()); CommentManager.get(m_provider).removeListener(m_internalCommentListener); } /** * Updates the node when global comments associated with the node change. */ private class InternalCommentListener extends CommentListenerAdapter { @Override public void appendedFunctionNodeComment(final INaviFunctionNode functionNode, final IComment comment) { if (CFunctionNode.this.equals(functionNode)) { for (final IViewNodeListener listener : getListeners()) { if (listener instanceof INaviFunctionNodeListener) { try { ((INaviFunctionNodeListener) listener).appendedFunctionNodeComment(functionNode, comment); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } } } @Override public void deletedFunctionNodeComment(final INaviFunctionNode functionNode, final IComment comment) { if (CFunctionNode.this.equals(functionNode)) { for (final IViewNodeListener listener : getListeners()) { if (listener instanceof INaviFunctionNodeListener) { try { ((INaviFunctionNodeListener) listener).deletedFunctionNodeComment(functionNode, comment); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } } } @Override public void editedFunctionNodeComment(final INaviFunctionNode functionNode, final IComment comment) { if (CFunctionNode.this.equals(functionNode)) { for (final IViewNodeListener listener : getListeners()) { if (listener instanceof INaviFunctionNodeListener) { try { ((INaviFunctionNodeListener) listener).editedFunctionNodeComment(functionNode, comment); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } } } @Override public void initializedFunctionNodeComments(final INaviFunctionNode functionNode, final List<IComment> comments) { if (CFunctionNode.this.equals(functionNode)) { for (final IViewNodeListener listener : getListeners()) { if (listener instanceof INaviFunctionNodeListener) { try { ((INaviFunctionNodeListener) listener).initializedFunctionNodeComment(functionNode, comments); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } } } } }