001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2016 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.gui; 021 022import antlr.ASTFactory; 023import antlr.collections.AST; 024import com.puppycrawl.tools.checkstyle.api.DetailAST; 025import com.puppycrawl.tools.checkstyle.api.TokenTypes; 026import com.puppycrawl.tools.checkstyle.utils.TokenUtils; 027 028/** 029 * The model that backs the parse tree in the GUI. 030 * 031 * @author Lars Kühne 032 */ 033public class ParseTreeTablePModel { 034 035 /** Column names. */ 036 private static final String[] COLUMN_NAMES = { 037 "Tree", "Type", "Line", "Column", "Text", 038 }; 039 040 /** 041 * The root node of the tree table model. 042 */ 043 private final Object root; 044 045 /** 046 * @param parseTree DetailAST parse tree. 047 */ 048 public ParseTreeTablePModel(DetailAST parseTree) { 049 root = createArtificialTreeRoot(); 050 setParseTree(parseTree); 051 } 052 053 /** 054 * Creates artificial tree root. 055 * @return artificial tree root. 056 */ 057 private static DetailAST createArtificialTreeRoot() { 058 final ASTFactory factory = new ASTFactory(); 059 factory.setASTNodeClass(DetailAST.class.getName()); 060 return (DetailAST) factory.create(TokenTypes.EOF, "ROOT"); 061 } 062 063 /** 064 * Set parse tree. 065 * @param parseTree DetailAST parse tree. 066 */ 067 protected final void setParseTree(DetailAST parseTree) { 068 ((AST) root).setFirstChild(parseTree); 069 } 070 071 /** 072 * @return the number of available columns. 073 */ 074 public int getColumnCount() { 075 return COLUMN_NAMES.length; 076 } 077 078 /** 079 * @param column the column number 080 * @return the name for column number {@code column}. 081 */ 082 public String getColumnName(int column) { 083 return COLUMN_NAMES[column]; 084 } 085 086 /** 087 * @param column the column number 088 * @return the type for column number {@code column}. 089 */ 090 public Class<?> getColumnClass(int column) { 091 final Class<?> columnClass; 092 093 switch (column) { 094 case 0: 095 columnClass = ParseTreeTableModel.class; 096 break; 097 case 1: 098 columnClass = String.class; 099 break; 100 case 2: 101 columnClass = Integer.class; 102 break; 103 case 3: 104 columnClass = Integer.class; 105 break; 106 case 4: 107 columnClass = String.class; 108 break; 109 default: 110 columnClass = Object.class; 111 } 112 return columnClass; 113 } 114 115 /** 116 * @param node the node 117 * @param column the column number 118 * @return the value to be displayed for node {@code node}, 119 * at column number {@code column}. 120 */ 121 public Object getValueAt(Object node, int column) { 122 final DetailAST ast = (DetailAST) node; 123 final Object value; 124 125 switch (column) { 126 case 1: 127 value = TokenUtils.getTokenName(ast.getType()); 128 break; 129 case 2: 130 value = ast.getLineNo(); 131 break; 132 case 3: 133 value = ast.getColumnNo(); 134 break; 135 case 4: 136 value = ast.getText(); 137 break; 138 default: 139 value = null; 140 } 141 return value; 142 } 143 144 /** 145 * Returns the child of parent at index. 146 * @param parent the node to get a child from. 147 * @param index the index of a child. 148 * @return the child of parent at index. 149 */ 150 public Object getChild(Object parent, int index) { 151 final DetailAST ast = (DetailAST) parent; 152 int currentIndex = 0; 153 AST child = ast.getFirstChild(); 154 while (currentIndex < index) { 155 child = child.getNextSibling(); 156 currentIndex++; 157 } 158 return child; 159 } 160 161 /** 162 * Returns the number of children of parent. 163 * @param parent the node to count children for. 164 * @return the number of children of the node parent. 165 */ 166 public int getChildCount(Object parent) { 167 final DetailAST ast = (DetailAST) parent; 168 return ast.getChildCount(); 169 } 170 171 /** 172 * @return the root. 173 */ 174 public Object getRoot() { 175 return root; 176 } 177 178 /** 179 * Whether the node is a leaf. 180 * @param node the node to check. 181 * @return true if the node is a leaf. 182 */ 183 public boolean isLeaf(Object node) { 184 return getChildCount(node) == 0; 185 } 186 187 /** 188 * Return the index of child in parent. If either <code>parent</code> 189 * or <code>child</code> is <code>null</code>, returns -1. 190 * If either <code>parent</code> or <code>child</code> don't 191 * belong to this tree model, returns -1. 192 * 193 * @param parent a node in the tree, obtained from this data source. 194 * @param child the node we are interested in. 195 * @return the index of the child in the parent, or -1 if either 196 * <code>child</code> or <code>parent</code> are <code>null</code> 197 * or don't belong to this tree model. 198 */ 199 public int getIndexOfChild(Object parent, Object child) { 200 int index = -1; 201 for (int i = 0; i < getChildCount(parent); i++) { 202 if (getChild(parent, i).equals(child)) { 203 index = i; 204 break; 205 } 206 } 207 return index; 208 } 209 210 /** 211 * Indicates whether the the value for node {@code node}, 212 * at column number {@code column} is editable. 213 * 214 * @param column the column number 215 * @return true if editable 216 */ 217 public boolean isCellEditable(int column) { 218 return getColumnClass(column).equals(ParseTreeTablePModel.class); 219 } 220}